#include <unistd.h>
#include <grass/gis.h>
#include <grass/display.h>
#include "graphics.h"
#include "colors.h"

static int save_colors(char *, char *, struct Colors *);
static int yes(char *, char *);

#define XSCALE  2.0
#define YSCALE  2.0

#define WRITE_STATUS \
    Write_status(cur_red, cur_grn, cur_blu, shift_incr, at_cat, hi_mode)

#define WRITE_CATS      Write_cats(categories, at_cat)

int
interact(struct Categories *categories, struct Colors *colors, char *name,
	 char *mapset)
{
    char buffer[128];
    CELL at_cat, tmp;
    int hi_mode;
    int hi_save_mode;
    int shift_incr;
    int cur_char;
    int red_hi;
    int grn_hi;
    int blu_hi;
    int cur_red;
    int cur_grn;
    int cur_blu;
    int colors_changed;
    int quit;

    set_signals();
    red_hi = 0;
    grn_hi = 0;
    blu_hi = 0;
    hi_mode = 0;
    hi_save_mode = 0;

    colors_changed = 0;
    Rast_set_c_null_value(&at_cat, 1);
    Rast_get_c_color(&at_cat, &cur_red, &cur_grn, &cur_blu, colors);
    shift_incr = 10;

    Initialize_curses();

    WRITE_CATS;

    Write_menu();

    WRITE_STATUS;

    /*  mark_category(at_cat, 1) ; */

    while (1) {
	R_flush();
	cur_char = getchar() & 0177;
	sprintf(buffer, "  %c", cur_char);
	Write_message(2, buffer);
	switch (cur_char) {
	case '*':
	    Replot_screen();
	    break;
	case 'Q':
	    quit = 1;
	    if (colors_changed) {
		if (yes("Colors changed", "Save the changes? (y/n)"))
		    quit = save_colors(name, mapset, colors);
		else
		    quit = yes("Quit anyway? (y/n)", "");
	    }
	    if (quit) {
		Clear_message();
		Write_message(2, "Bye   ");
		G_sleep(2);

		Close_curses();
		return (0);
	    }
	    break;

	case 'D':
	case 'U':
	case 'd':
	case 'u':
	    if (hi_mode && !hi_save_mode) {
		Rast_get_c_color(&at_cat, &cur_red, &cur_grn, &cur_blu, colors);
	    }
	    /*              tmark_category(at_cat, 0) ; */
	    if (Rast_is_c_null_value(&at_cat))
		tmp = 0;
	    else
		tmp = at_cat + 1;
	    switch (cur_char) {
	    case 'd':
		tmp++;
		break;
	    case 'u':
		tmp += categories->num + 1;
		break;
	    case 'D':
		tmp += 10;
		break;
	    case 'U':
		if (categories->num > 10)
		    tmp += categories->num - 9;
		else
		    tmp += categories->num - (categories->num - 1);
		break;
	    }
	    tmp = tmp % (categories->num + 2);	/* changed 11/99 M.N. */
	    if (!tmp)
		Rast_set_c_null_value(&at_cat, 1);
	    else
		at_cat = tmp - 1;

	    if (hi_mode) {
		cur_red = red_hi;
		cur_grn = grn_hi;
		cur_blu = blu_hi;
		if (hi_save_mode) {
		    Rast_set_c_color(at_cat, cur_red, cur_grn, cur_blu, colors);
		    colors_changed = 1;
		}
	    }
	    else {
		Rast_get_c_color(&at_cat, &cur_red, &cur_grn, &cur_blu, colors);
	    }

	    WRITE_CATS;
	    WRITE_STATUS;
	    /*              mark_category(at_cat, 1) ; */
	    break;
	case 'r':
	case 'R':
	case 'g':
	case 'G':
	case 'b':
	case 'B':
	    if (hi_mode) {
		switch (cur_char) {
		case 'r':
		    red_hi = shift_color(red_hi, -shift_incr);
		    break;
		case 'R':
		    red_hi = shift_color(red_hi, shift_incr);
		    break;
		case 'g':
		    grn_hi = shift_color(grn_hi, -shift_incr);
		    break;
		case 'G':
		    grn_hi = shift_color(grn_hi, shift_incr);
		    break;
		case 'b':
		    blu_hi = shift_color(blu_hi, -shift_incr);
		    break;
		case 'B':
		    blu_hi = shift_color(blu_hi, shift_incr);
		    break;
		}
		cur_red = red_hi;
		cur_grn = grn_hi;
		cur_blu = blu_hi;
		if (hi_save_mode) {
		    Rast_set_c_color(at_cat, cur_red, cur_grn, cur_blu, colors);
		    colors_changed = 1;
		}
	    }
	    else {
		Rast_get_c_color(&at_cat, &cur_red, &cur_grn, &cur_blu, colors);
		switch (cur_char) {
		case 'r':
		    cur_red = shift_color(cur_red, -shift_incr);
		    break;
		case 'R':
		    cur_red = shift_color(cur_red, shift_incr);
		    break;
		case 'g':
		    cur_grn = shift_color(cur_grn, -shift_incr);
		    break;
		case 'G':
		    cur_grn = shift_color(cur_grn, shift_incr);
		    break;
		case 'b':
		    cur_blu = shift_color(cur_blu, -shift_incr);
		    break;
		case 'B':
		    cur_blu = shift_color(cur_blu, shift_incr);
		    break;
		}
		Rast_set_c_color(at_cat, cur_red, cur_grn, cur_blu, colors);
		colors_changed = 1;
	    }
	    WRITE_STATUS;
	    break;
	case 'i':
	    shift_incr = shift_color(shift_incr, -1);
	    WRITE_STATUS;
	    break;
	case 'I':
	    shift_incr = shift_color(shift_incr, 1);
	    WRITE_STATUS;
	    break;
	case '+':
	    Rast_shift_c_colors(1, colors);
	    if (hi_mode) {
		cur_red = red_hi;
		cur_grn = grn_hi;
		cur_blu = blu_hi;
		if (hi_save_mode)
		    Rast_set_c_color(at_cat, cur_red, cur_grn, cur_blu, colors);
	    }
	    colors_changed = 1;
	    WRITE_STATUS;
	    break;
	case '-':
	    Rast_shift_c_colors(-1, colors);
	    if (hi_mode) {
		cur_red = red_hi;
		cur_grn = grn_hi;
		cur_blu = blu_hi;
		if (hi_save_mode)
		    Rast_set_c_color(at_cat, cur_red, cur_grn, cur_blu, colors);
	    }
	    colors_changed = 1;
	    WRITE_STATUS;
	    break;
	case 'c':		/* Writeout color lookup table */
	    colors_changed = 0;
	    save_colors(name, mapset, colors);
	    break;

	case 't':
	    Clear_message();
	    Write_message(1, "toggling new color table...");
	    table_toggle(name, mapset, colors);
	    /*Clear_message() ; */
	    if (hi_mode) {
		cur_red = red_hi;
		cur_grn = grn_hi;
		cur_blu = blu_hi;
		if (hi_save_mode)
		    Rast_set_c_color(at_cat, cur_red, cur_grn, cur_blu, colors);
	    }
	    colors_changed = 1;
	    break;
	case 'h':
	case 'H':
	    if (hi_mode) {
		Rast_get_c_color(&at_cat, &cur_red, &cur_grn, &cur_blu, colors);
		hi_mode = 0;
		hi_save_mode = 0;
	    }
	    else {
		cur_red = red_hi;
		cur_grn = grn_hi;
		cur_blu = blu_hi;
		hi_mode = 1;
		if (cur_char == 'H') {
		    Rast_set_c_color(at_cat, cur_red, cur_grn, cur_blu, colors);
		    hi_save_mode = 1;
		    colors_changed = 1;
		}
	    }
	    WRITE_STATUS;

	    break;
	default:

	    sprintf(buffer, "  %c - Unknown Command", cur_char);
	    Write_message(2, buffer);
	    break;
	}
    }
}

int shift_color(int colr, int shift)
{
    colr = colr + shift;
    if (colr < 0)
	colr = 0;
    if (colr > 255)
	colr = 255;
    return (colr);
}

static int yes(char *msg1, char *msg2)
{
    int c;

    Clear_message();
    Write_message(1, msg1);
    Write_message(2, msg2);

    while (1) {
	c = getchar() & 0177;
	switch (c) {
	case 'y':
	case 'Y':
	    Clear_message();
	    return 1;

	case 'n':
	case 'N':
	    Clear_message();
	    return 0;
	}
	putchar('\7');
    }
}

static int save_colors(char *name, char *mapset, struct Colors *colors)
{
    Clear_message();
    Write_message(2, "Writing color table      ");

    Rast_write_colors(name, mapset, colors);
    Clear_message();
    return 1;
}
