/*
    Tucnak - VHF contest log
    Copyright (C) 2002-2015  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.

    UTF-8 detect: ěščřžýáíé
*/

#include "header.h"

#include "edi.h"
#include "fifo.h"
#include "inputln.h"
#include "kbdbind.h"
#include "kbd.h"
#include "main.h"
#include "net.h"
#include "qsodb.h"
#include "tsdl.h"
#include "session.h"
#include "sked.h"
#include "subwin.h"
#include "subwin.h"

static char callsign[EQSO_LEN], locator[EQSO_LEN];
static char time_str[EQSO_LEN], remark[MAX_STR_LEN]; 

int sw_sked_kbd_func(struct subwin *sw, struct event *ev, int fw){
	struct sked *sked;
	int i;
    if (!aband) return 0;

    if (sw->il && (
        sw->il->wasctrlv ||    
		(ev->x!='[' && ev->x!=']') )){
	    if (inputln_func(sw->il, ev)) return 1;
	}

    switch(kbd_action(KM_MAIN,ev)){
        case ACT_ESC:
            return 0;
            break;
        case ACT_DOWN:
            sw->offset--;
            sw->check_bounds(sw);
            redraw_later();
            return 1;
        case ACT_UP:
            sw->offset++;
            sw->check_bounds(sw);
            redraw_later();
            return 1;
        case ACT_PAGE_DOWN:
            sw->offset -= sw->h - 1;;
            sw->check_bounds(sw);
            redraw_later();
            return 1;
        case ACT_PAGE_UP:
            sw->offset += sw->h - 1;;
            sw->check_bounds(sw);
            redraw_later();
            return 1;
        case ACT_HOME:
            sw->offset = aband->skeds->len - sw->h; 
            sw->check_bounds(sw);
            redraw_later();
            return 1;
        case ACT_END:
            sw->offset = 0;
            sw->check_bounds(sw);
            redraw_later();
            return 1;
		case ACT_SCROLL_LEFT:
			if (sw->ho>0) sw->ho--;
            redraw_later();
            return 1;
		case ACT_SCROLL_RIGHT:
			sw->ho++;
            redraw_later();
            return 1;
		case ACT_ENTER:
			if (aband->readonly) return 1;
			i = aband->skeds->len - sw->offset - 1;
			if (i < 0 || i >= aband->skeds->len) break;
			sked = (struct sked *)g_ptr_array_index(aband->skeds, i);
			process_input(aband, sked->callsign, 0);
			il_add_to_history(INPUTLN(aband), sked->callsign);
			process_input(aband, sked->locator, 0);
			aband->tmpqsos[0].ulocator = 1;
			return 1;
    }
    return 0;
}

int sw_sked_mouse_func(struct subwin *sw, struct event *ev, int fw){
    if (!aband) return 0;
    return sw_fifo_mouse_func(sw, ev, fw);
}

gchar *sw_sked_sprint(struct sked *sked){
    double qrb,qtf; 
    int qrb_int,qtf_int;
    gchar *c, *deg;

    qrbqtf(ctest->pwwlo, sked->locator, &qrb, &qtf, NULL, 2);
    qrb_int=(int)qrb;
    qtf_int=(int)(qtf+0.5);
    if (qrb_int < 0.1) {
        qrb_int=0;
        qtf_int=0;
    }  

#ifdef Z_HAVE_SDL    
    if (sdl)
        deg = "°";
    else
#endif      
    deg = VTEXT(T_DEGREE);
            
    c=g_strdup_printf(VTEXT(T_SKED_FORMAT),
            sked->operator_, sked->src_shortpband, sked->pband, sked->qrg, 
            sked->callsign, sked->locator, qrb_int, qtf_int, 
            deg, sked->time_str, sked->remark);

    return c;
}

void sw_sked_redraw(struct subwin *sw, struct band *band, int flags){
    int i, index;
    gchar *c;
    struct sked *sked;
	int color;
    
    if (!aband) return;
    /*dbg("sw_log_redraw  log->len=%d sw->h=%d sw->offset=%d \n", fifo_len(sw->fifo), sw->h, sw->offset);*/
    
	
    for (i = 0; i < sw->h; i++){
        index = aband->skeds->len - sw->offset - sw->h+i;
        if (index < 0 || index >= aband->skeds->len) continue;
        sked = (struct sked *)g_ptr_array_index(aband->skeds, index);
        c = sw_sked_sprint(sked);
		
		if (i == sw->h - 1) {
			color = sked->worked ? COL_INV | COL_DARKYELLOW : COL_INV;
			fill_area(sw->x, sw->y + i, sw->w, 1, COL_INV);
		}else{
			color = sked->worked ? COL_DARKYELLOW : COL_NORM;
		}

	    print_text(sw->x, sw->y + i, sw->w, c + sw->ho, color);
        g_free(c);
    }
}

void sw_sked_check_bounds(struct subwin *sw){
    if (!aband) return;
    
    /*if (sw->offset < 0) sw->offset=0;*/
    if (sw->offset > (int)aband->skeds->len - 1) {
        sw->offset = (int)aband->skeds->len - 1;
    }
    if (sw->offset < 0) sw->offset=0;
}
/* 11.52 OK1ZIA@144: 432 MHz .250 OK1MCS in JN69QR (1234km, 359gr) at 12:00 we call (this is a remark ) */
void sw_sked_read(gchar *str, int from_my){
    int i;
    struct band *b;
    struct sked *sked;
    struct zstring *zs;
    struct subwin *sw;
    gchar *c, *d;

    
    dbg("sw_sked_read('%s', %d)\n", str, from_my);
    zs = zstrdup(str);
    sked = sked_parse(zs);
    if (!sked) {
        dbg("bad format of sked '%s'\n", str);
        return;
    }
    zfree(zs);

    b=find_band_by_pband(sked->pband);
    if (!b){
        dbg("band '%s' not found\n", sked->pband);
        free_sked(sked);
        return;
    }

    g_ptr_array_add(b->skeds, sked);
    b->dirty_save = 1;

    if (b->readonly == 0){
        for (i=0; i<gses->subwins->len; i++){
            sw = g_ptr_array_index(gses->subwins, i);
//            dbg("type=%d ontop=%d\n", sw->type, sw->ontop);
            if (sw->type != SWT_SKED) continue;
            if (sw->ontop) continue;
            sw->unread=1;
        }
        c = sw_sked_sprint(sked);
		d = g_strdup_printf("Sked %s", c);
        log_adds(d);
        g_free(c);
        g_free(d);
        skedw_create(b);
    }
    check_autosave();
    redraw_later();
}



char qrg_str[EQSO_LEN];
char pband[EQSO_LEN]="Select"; /* TODO VTEXT(T_SELECT) */
char oldpband[EQSO_LEN]=""; 
/*, time_str[EQSO_LEN], callsign[EQSO_LEN]*/;
/*char locator[EQSO_LEN], remark[MAX_STR_LEN]; */
                       
int pband_int=-1;

void refresh_sked(struct qso *q)
{
    char s[10], *c;
    time_t now;
    struct tm utc;
    struct zstring *zs;
    char sked_time_str[32];

    time(&now);
    gmtime_r(&now, &utc);
    
    dbg("refresh_sked\n");

    g_snprintf(sked_time_str, 30, "%d.%02d", utc.tm_hour, utc.tm_min);
    safe_strncpy0(s, aband->pband, 10); 
    c = strchr(s, ' ');
    if (c) *c='\0';
    z_str_uc(callsign);
    z_str_uc(locator);

    zs = zconcatesc(sked_time_str, aband->operator_, s, qrg_str, 
            "0", pband, time_str, callsign, 
            locator, remark, NULL);
    
    sw_sked_read(zs->str,1);

    c = g_strdup_printf("SK %s\n", zs->str);
    rel_write_all(c);
    g_free(c);
    zfree(zs);
}                    

void sked_fn(struct dialog_data *dlg)
{
    //struct terminal *term = dlg->win->term;
    //int max = 0, min = 0;
    //int w, rw;
    //int y = -1;
    struct band *band;

/*    dbg("items[0]=%p\n",dlg->items[0]); 
    dbg("items[0].item=%p\n",dlg->items[0].item); 
    dbg("items[0].cdata=%p\n",dlg->items[0].cdata); */
    if (strcmp(pband, oldpband)!=0){
        strcpy(oldpband, pband);
 /*       dbg("pband=%s\n");*/
        band = find_band_by_pband(pband);
        if (band) {
            safe_strncpy0(dlg->items[1].cdata, band->skedqrg, EQSO_LEN);
            dlg->items[1].cpos = strlen(dlg->items[1].cdata);
        }
    }
}

void sked(void){
    struct dialog *d;
    int i;
    struct band *band;
    
    if (pband_int<0){
        for (i = 0; i < ctest->bands->len; i++) {
            band = (struct band *)g_ptr_array_index(ctest->bands, i);
            if (band==aband) break;
        }
        i++;
        if (i<ctest->bands->len){
            band = (struct band *)g_ptr_array_index(ctest->bands, i);
            safe_strncpy0(pband, band->pband, EQSO_LEN);
            pband_int = i;
        }
    }
	if (pband_int<0) pband_int=0;
    band = (struct band *)g_ptr_array_index(ctest->bands, pband_int);
	if (band) safe_strncpy0(qrg_str, band->skedqrg, EQSO_LEN);
	

    if (!(d = (struct dialog*)g_malloc(sizeof(struct dialog) + 15 * sizeof(struct dialog_item)))) return;
    memset(d, 0, sizeof(struct dialog) + 15 * sizeof(struct dialog_item));
    d->title = VTEXT(T_SEND_SKED);
	d->fn = dlg_pf_fn;
    d->fn2 = sked_fn;
    d->refresh = (void (*)(void *))refresh_sked;
    d->refresh_data = NULL;
	d->y0 = 1;
	i = -1;

    d->items[++i].type = D_BUTTON;
    d->items[i].gid  = 0;
    d->items[i].fn   = dlg_pband;
    d->items[i].text = pband;
	d->items[i].msg = CTEXT(T_BAND);
	d->items[i].wrap = 1;
    
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = qrg_str;
	d->items[i].msg = CTEXT(T_QRG);
	d->items[i].wrap = 1;
    
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = 61;
    d->items[i].data = remark;
    d->items[i].maxl = EQSO_LEN;
	d->items[i].msg = CTEXT(T_REMARK),
	d->items[i].wrap = 1;
    
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = callsign;
	d->items[i].msg = CTEXT(T_CALLSIGN2);
	d->items[i].wrap = 1;
    
    d->items[++i].type = D_FIELD;
    d->items[i].dlen = EQSO_LEN;
    d->items[i].data = locator;
	d->items[i].msg = CTEXT(T_WWL);
	d->items[i].wrap = 1;
   
    
	d->items[i].wrap++;
    d->items[++i].type = D_BUTTON;
    d->items[i].gid = B_ENTER;
    d->items[i].fn = ok_dialog;
    d->items[i].text = VTEXT(T_OK);
    
    d->items[++i].type = D_BUTTON;
    d->items[i].gid = B_ESC;
    d->items[i].fn = cancel_dialog;
    d->items[i].text = VTEXT(T_CANCEL);
	d->items[i].align = AL_BUTTONS;
	d->items[i].wrap = 1;
    
    d->items[++i].type = D_END;
    do_dialog(d, getml(d, NULL));
}
                               
void sked_from_tmpqso(struct tmpqso *tmpqso)
{
    time_t now;
    struct tm utc;

    time(&now);
    //now+=cfg->skedshift*60;
    gmtime_r(&now, &utc);
           
    strcpy(qrg_str,"");
    /* pband */
    g_snprintf(time_str, EQSO_LEN, "%d.%02d", utc.tm_hour, utc.tm_min);
    safe_strncpy0(callsign, tmpqso->callsign, EQSO_LEN); z_str_uc(callsign);
    safe_strncpy0(locator,  tmpqso->locator,  EQSO_LEN); z_str_uc(locator);
    strcpy(remark, "");

    sked();
}

void sked_from_qso(struct qso *qso)
{
    time_t now;
    struct tm utc;

    time(&now);
    //now+=cfg->skedshift*60;
    gmtime_r(&now, &utc);
           
    strcpy(qrg_str,"");
    /* pband */
    g_snprintf(time_str, EQSO_LEN, "%d.%02d", utc.tm_hour, utc.tm_min);
    safe_strncpy0(callsign, qso->callsign, EQSO_LEN); z_str_uc(callsign);
    safe_strncpy0(locator,  qso->locator,  EQSO_LEN); z_str_uc(locator);
    strcpy(remark, "");

    sked();
}



void sked_pband_func(void *arg){
    struct band *band;
    int active;

    active=GPOINTER_TO_INT(arg);
    dbg("sked_pband_func(%d)\n", active);
    if (active<0 || active>=ctest->bands->len) return;
    
    pband_int = active;
    band = g_ptr_array_index(ctest->bands, pband_int);
    safe_strncpy0(pband, band->pband, EQSO_LEN);
 	safe_strncpy0(qrg_str, band->skedqrg, EQSO_LEN);
    redraw_later();
}

void sked_pband(int apband_int)                   
{                                                                                             
    int i, sel;
    struct menu_item *mi;
    struct band *band;
    
    if (!(mi = new_menu(1))) return;
    for (i = 0; i < ctest->bands->len; i++) {
        band = (struct band *)g_ptr_array_index(ctest->bands, i);
        add_to_menu(&mi, band->pband, "", "", MENU_FUNC sked_pband_func, GINT_TO_POINTER(i), 0);
    }
    sel = apband_int;
    if (sel < 0) sel = 0;
    if (sel>=ctest->bands->len) sel=0;
    do_menu_selected(mi, NULL, sel);
}


int dlg_pband(struct dialog_data *dlg, struct dialog_item_data *di){
    sked_pband(pband_int); 
    return 0;
}

struct zstring *sked_format(struct sked *sked){
    struct zstring *zs;

    zs = zconcatesc(sked->sked_time, sked->operator_, sked->src_shortpband, sked->qrg,
			"0", sked->pband, sked->time_str, sked->callsign,
            sked->locator, sked->remark, NULL);

    return zs;
}

struct sked *sked_parse(struct zstring *zstr){
    int tokens;
    struct sked *sked;

    tokens = ztokens(zstr);
    if (tokens<10){
        dbg("bad format of sked '%s'\n", zstr->str);
        return NULL;
    }

    sked = g_new0(struct sked, 1);
    sked->sked_time = g_strdup(ztokenize(zstr, 1));
    sked->operator_ = g_strdup(ztokenize(zstr, 0));
    sked->src_shortpband = g_strdup(ztokenize(zstr, 0));
    sked->qrg = g_strdup(ztokenize(zstr, 0));
    ztokenize(zstr, 0); // we_call
    sked->pband = g_strdup(ztokenize(zstr, 0));
    sked->time_str = g_strdup(ztokenize(zstr, 0));
    sked->callsign = g_strdup(ztokenize(zstr, 0));
    sked->locator = g_strdup(ztokenize(zstr, 0));
    sked->remark = g_strdup(ztokenize(zstr, 0));

    return sked;
}

void free_sked(struct sked *sked){

    g_free(sked->sked_time);
    g_free(sked->operator_);
    g_free(sked->src_shortpband);
    g_free(sked->qrg);
    g_free(sked->pband);
    g_free(sked->time_str);
    g_free(sked->callsign);
    g_free(sked->locator);
    g_free(sked->remark);
    g_free(sked);
}

void recalc_worked_skeds(struct band *band){
    int i;

    for (i=0; i<band->skeds->len; i++){
        struct sked *sked;

        sked = g_ptr_array_index(band->skeds, i);
        sked->worked = get_qso_by_callsign(band, sked->callsign) != NULL;
        //dbg("sked %s worked=%d\n", sked->callsign, sked->worked);
    }
}


/* ***************** SKED WINDOW ******************* */



void draw_skedwindow(struct skedwin_data *skedwdata){
    int y,index;

    fill_area(skedwdata->x+1, skedwdata->y+1, skedwdata->w-2, skedwdata->h-2, COL_INV); 
    draw_frame(skedwdata->x, skedwdata->y, skedwdata->w, skedwdata->h, COL_INV, 1); 
    print_text(skedwdata->x + 5, skedwdata->y, -1, VTEXT(T_SKEDS), COL_NORM);

    if (!skedwdata->band) return;
    for (y=0;y<skedwdata->h - 2; y++){
        gchar *c;
        struct sked *sked;

        index = skedwdata->band->skeds->len - skedwdata->h + 2 + y;
        if (index<0 || index>=skedwdata->band->skeds->len) continue;
        sked = g_ptr_array_index(skedwdata->band->skeds, index);
        c = sw_sked_sprint(sked);
	    print_text(skedwdata->x + 2, skedwdata->y+y+1, skedwdata->w - 4, c, COL_INV);
        g_free(c);
    }
}

void skedwindow_func(struct window *win, struct event *ev, int fwd){
    struct skedwin_data *skedwdata;
    
    skedwdata = (struct skedwin_data *)win->data;
    
//    dbg("skedwindow_func [%d,%d,%d,%d]\n",ev->ev,ev->x,ev->y,ev->b);

    switch (ev->ev) {
        case EV_INIT:
            win->data = skedwdata = gses->skedwdata;

        case EV_RESIZE:
            skedwdata->x = gses->ontop->x;
            skedwdata->y = gses->ontop->y;
            skedwdata->w = gses->ontop->w;
            skedwdata->h = 2 + cfg->skedcount;
            
        case EV_REDRAW:
            draw_skedwindow(skedwdata);
            break;
        case EV_ABORT:
            if (gses) gses->skedwdata = NULL;
            /* mem_free(cwwdata);  already in terminal.c:196 (delete_window) */ 
            break;
        case EV_KBD:
            if (ev->x == KBD_ESC){
                skedwdata->esccnt++;
                if (skedwdata->esccnt==3){
                    delete_window_ev(win, ev);
                    return;
                }
            }else{
                skedwdata->esccnt=0;
            }
            dbg("esccnt=%d\n", skedwdata->esccnt);
            win->next->handler(win, ev, 0);
            break;
        default:
            win->next->handler(win, ev, 0);
    }
}

void skedw_timer(void *arg){
    struct window *w;
    if (!gses) return;

    gses->skedw_timer_id = 0;

    if (gses->skedwdata == NULL) return; // duplicate check but...
    foreach(w,term->windows){
        if (w->data != gses->skedwdata) continue;
        delete_window(w);
        break;
    } 
}

void skedw_create(struct band *b){
    if (cfg->skedcount <= 0) return;
    if (gses->skedw_timer_id > 0) zselect_timer_kill(zsel, gses->skedw_timer_id); 
    gses->skedw_timer_id = zselect_timer_new(zsel, 5000, skedw_timer, NULL);

    if (gses->skedwdata) {
        gses->skedwdata->band = b;
        return;
    }

    gses->skedwdata = g_malloc(sizeof(struct skedwin_data));
    memset(gses->skedwdata, 0, sizeof(struct skedwin_data));
    gses->skedwdata->band = b;
            
    add_window_at_pos(skedwindow_func, NULL, gseswin->prev);
}

