/*
    Tucnak - VHF contest log
    Copyright (C) 2013 Ladislav Vaiz <ok1zia@nagano.cz>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    version 2 as published by the Free Software Foundation.

*/

#include "state.h"

#include "dxc.h"
#include "edi.h"
#include "inputln.h"
#include "kst.h"
#include "subwin.h"
#include "qsodb.h"


struct state *init_state(void){
	struct state *state = g_new0(struct state, 1);
	state->hash = g_hash_table_new(g_str_hash, g_str_equal);
	return state;
}

void free_state(struct state *state){
	zg_hash_free(state->hash);
	g_free(state);
}


void state_putstr(struct state *state, char *key, char *val){
	g_hash_table_insert(state->hash, key, val);
}

void state_dupstr(struct state *state, const char *key, const char *val){
//    dbg("state_dupstr 1 state=%p hash=%p key=%p val=%p\n", state, state->hash, key, val);
//    dbg("state_dupstr 2 \n");
	g_hash_table_insert(state->hash, g_strdup(key), g_strdup(val));
//    dbg("state_dupstr 3\n");
}

const char *state_getstr(struct state *state, const char *key){
	const char *c = (const char*)g_hash_table_lookup(state->hash, key);
	if (!c) return "";
	return c;
}


void state_test(struct state *state){
	int i, j ;
    
	state_dupstr(state, "gln_cdata", "GSES INPUTLN");
	state_dupstr(state, "ctest", "20130610.1");
	state_dupstr(state, "aband", "10 GHz");
	state_dupstr(state, "ontop", "3");

	for (i = 0; i < cfg->bands->len; i++){
		struct config_band *b = (struct config_band *)g_ptr_array_index(cfg->bands, i);
		state_putstr(state, g_strdup_printf("band%c_il_cdata", z_char_lc(b->bandchar)), g_strdup_printf("Band %c inputln", z_char_lc(b->bandchar)));
		state_putstr(state, g_strdup_printf("band%c_il_hlen", z_char_lc(b->bandchar)), g_strdup("3"));
		for (j = 0; j < 3; j++){
			state_putstr(state, 
				g_strdup_printf("band%c_il_h%d", z_char_lc(b->bandchar), j), 
				g_strdup_printf("Band %c inputln history %d", z_char_lc(b->bandchar), j));
		}
	}

	for	(i = 0; i < gses->subwins->len; i++){
		struct subwin *sw = (struct subwin *)g_ptr_array_index(gses->subwins, i);
		if (sw->il){
			state_putstr(state, g_strdup_printf("sw%d_il_cdata", i+1), g_strdup_printf("Subwin %d inputline", i+1));
			state_putstr(state, g_strdup_printf("sw%d_il_hlen", i+1), g_strdup("4"));
			for (j = 0; j < 4; j++){
				state_putstr(state, 
					g_strdup_printf("sw%d_il_h%d", i+1, j), 
					g_strdup_printf("Subwin %d inputln history %d", i+1, j));
			}
		}
		if (sw->type == SWT_DXC || sw->type == SWT_KST){
			state_putstr(state, g_strdup_printf("sw%d_connected", i+1), g_strdup("0"));
		}
	}
}


void state_save(struct state *state){
	//char *c, *key;
	int i, j;

    if (!gses) return; // happens when called from android OnSaveInstance when updating package
    state_dupstr(state, "saved", "y");
    state_dupstr(state, "gln_cdata", gses->il->cdata);
	state_dupstr(state, "ctest", ctest ? z_filename(ctest->directory) : "");
	state_dupstr(state, "aband", aband ? aband->pband : "");
    if (ctest != NULL){
        for (i = 0; i < ctest->bands->len; i++){
            struct band *b = (struct band *)g_ptr_array_index(ctest->bands, i);
            if (b->il){
                state_putstr(state, g_strdup_printf("band%c_il_cdata", z_char_lc(b->bandchar)), g_strdup(b->il->cdata));
                state_putstr(state, g_strdup_printf("band%c_il_hlen", z_char_lc(b->bandchar)), g_strdup_printf("%d", b->il->history->len));
                for (j = 0; j < b->il->history->len; j++){
                    state_putstr(state, 
                        g_strdup_printf("band%c_il_h%d", z_char_lc(b->bandchar), j), 
                        g_strdup((char*)g_ptr_array_index(b->il->history, j)));
                }
            }
        }
    }
	for	(i = 0; i < gses->subwins->len; i++){
		struct subwin *sw = (struct subwin *)g_ptr_array_index(gses->subwins, i);
		if (sw->il){
			state_putstr(state, g_strdup_printf("sw%d_il_cdata", i+1), g_strdup(sw->il->cdata));
			state_putstr(state, g_strdup_printf("sw%d_il_hlen", i+1), g_strdup_printf("%d", sw->il->history->len));
			for (j = 0; j < sw->il->history->len; j++){
				state_putstr(state, 
					g_strdup_printf("sw%d_il_h%d", i+1, j), 
					g_strdup((char*)g_ptr_array_index(sw->il->history, j)));
			}
		}
		if (sw->type == SWT_DXC || sw->type == SWT_KST){
			state_putstr(state, g_strdup_printf("sw%d_connected", i+1), g_strdup(sw->sock < 0 ? "0" : "1"));
		}
		if (sw == gses->ontop) state_putstr(state, g_strdup("ontop"), g_strdup_printf("%d", i+1));
	}

}

void state_restore(struct state *state){
	const char *c;
	char *key;
	int i, j, len, ontop;
	struct band *b;

	c = state_getstr(state, "gln_cdata");
	g_strlcpy(gses->il->cdata, c, gses->il->dlen);
	gses->il->cpos = strlen(gses->il->cdata);

	c = state_getstr(state, "ctest");
	if (c && *c){
		load_contest_edi(c, 0);
		for (i = 0; i < ctest->bands->len; i++){
			struct band *b = (struct band *)g_ptr_array_index(ctest->bands, i);
			if (b->il){
				key = g_strdup_printf("band%c_il_cdata", z_char_lc(b->bandchar));
				c = state_getstr(state, key);
				if (c) {
					g_strlcpy(b->il->cdata, c, b->il->dlen);
					b->il->cpos = strlen(b->il->cdata);
				}
				g_free(key);

				key = g_strdup_printf("band%c_il_hlen", z_char_lc(b->bandchar));
				len = atoi(state_getstr(state, key));
				g_free(key);
				for (j = 0; j < len; j++){
					key = g_strdup_printf("band%c_il_h%d", z_char_lc(b->bandchar), j);
					c = state_getstr(state, key);
					g_ptr_array_add(b->il->history, g_strdup(c));
					g_free(key);
				}
			}
		}
	}

	c = state_getstr(state, "aband");
	b = find_band_by_pband((char *)c);
    if (b){
       // progress("Activating band %s", b->bandname);
        activate_band(b); /* b==NULL is handled by function */
    }

	c = state_getstr(state, "ontop");
	ontop = atoi(c);

	for	(i = 0; i < gses->subwins->len; i++){
		struct subwin *sw = (struct subwin *)g_ptr_array_index(gses->subwins, i);
		if (sw->il){
			key = g_strdup_printf("sw%d_il_cdata", i+1);
			c = state_getstr(state, key);
			if (c) {
				g_strlcpy(sw->il->cdata, c, sw->il->dlen);
				sw->il->cpos = strlen(sw->il->cdata);
			}
			g_free(key);

			key = g_strdup_printf("sw%d_il_hlen", i+1);
			len = atoi(state_getstr(state, key));
			g_free(key);
			for (j = 0; j < len; j++){
				key = g_strdup_printf("sw%d_il_h%d", i+1, j);
				c = state_getstr(state, key);
				g_ptr_array_add(sw->il->history, g_strdup(c));
				g_free(key);
			}
		}
		if (sw->type == SWT_DXC || sw->type == SWT_KST){
			key = g_strdup_printf("sw%d_connected", i+1);
			c = state_getstr(state, key);
			if (*c == '1'){
				if (sw->type == SWT_DXC) dxc_open_connection(sw, NULL);
				if (sw->type == SWT_KST) kst_open_connection(sw, NULL);
			}
			g_free(key);
		}
		if (i+1 == ontop) sw_set_ontop(ontop - 1, 0);
	}
}

void state_foreach(struct state *state, GHFunc func, gpointer user_data){
    g_hash_table_foreach(state->hash, func, user_data);
}

