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

#include "bfu.h"
#include "fifo.h"
#include "kst.h"
#include "qsodb.h"
#include "session.h"
#include "subwin.h"

#include "misc.h"

struct fifo *glog = NULL;
struct fifo *gtalk = NULL;
//static struct fifo *gsked = NULL;

struct fifo *init_fifo(int maxlen){
    struct fifo *fifo;

/*    dbg("init_fifo(%d)\n", maxlen);*/

    fifo = g_new0(struct fifo, 1);
    fifo->maxlen = maxlen;
    fifo->items = g_ptr_array_new();
    return fifo;
}


void free_fifo(struct fifo *fifo){
    sw_unset_unread(fifo);
    zg_ptr_array_free_all(fifo->items);
    g_free(fifo);
}

void drop_fifo(struct fifo *fifo){
    int i;
    for (i=fifo->items->len-1; i>=0; i--){
		g_free(g_ptr_array_index(fifo->items, i));
        g_ptr_array_remove_index_fast(fifo->items, i);
    }
}

void fifo_resize(struct fifo *fifo, int x, int y, int w, int h){
    fifo->x = x;
    fifo->y = y;
    fifo->w = w;
    fifo->h = h;
} 

int fifo_len(struct fifo *fifo){
    return fifo->items->len;
}

gchar *fifo_index(struct fifo *fifo, int index){
    return (char *)g_ptr_array_index(fifo->items, index);
}



static void fifo_check_len(struct fifo *fifo){
    gpointer p;
    
    if (fifo->items->len == fifo->maxlen){
        p = g_ptr_array_index(fifo->items, 0);   
        g_free(p);
        g_ptr_array_remove_index(fifo->items, 0);
    }
}


static gchar *hour_min(void){
    time_t now;
    struct tm utc;
    gchar *res;

    time(&now);
    gmtime_r(&now, &utc);

    res=g_strdup_printf("%2d:%02d",utc.tm_hour, utc.tm_min);
    return res;
}

void fifo_adds(struct fifo *fifo, gchar *str){
    int l,i;
    gchar *c, *now;
    struct subwin *sw;

    if (!fifo || !str) return;
    if (!fifo->withouttime){
        now = hour_min();
        c = g_strconcat(now, " ", str, NULL);
        g_free(now);
    }else{
        c = g_strdup(str);
    }
        
    
    l = strlen(c);
    if (l>0 && c[l-1]=='\n') c[l-1]='\0';
    if (l>0 && c[l-1]=='\r') c[l-1]='\0';

    if (gses){
        for (i=0; i<gses->subwins->len; i++){
            sw = (struct subwin *)g_ptr_array_index(gses->subwins, i);
            if (sw->fifo!=fifo) continue;
            if (sw->offset > 0 && sw->offset < sw->maxlen-sw->h) sw->offset++;
        }
    }
    
    g_ptr_array_add(fifo->items, c);
    if (ctest && ctest->logfile && fifo==glog){
        fprintf(ctest->logfile, "%s\n", c);
    }
    fifo_check_len(fifo);
    sw_set_unread(fifo);
    
    if (term) redraw_later();
        
}

void fifo_addf(struct fifo *fifo, char *m, ...){ 
    gchar *c, *d, *now;
    int l;
    va_list v;

    if (!fifo) return;
    
    va_start(v, m);
    c = g_strdup_vprintf(m, v);
    va_end(v);
    l = strlen(c);
    if (l>0 && c[l-1]=='\n') c[l-1]='\0';
    if (l>0 && c[l-1]=='\r') c[l-1]='\0';
    
    if (!fifo->withouttime){
        now = hour_min();
        d = g_strconcat(now, " ", c, NULL);
        g_free(now);
        g_free(c);
    }
    else{
        d=c;
    }
    
    g_ptr_array_add(fifo->items, d);
    if (ctest && ctest->logfile && fifo==glog){
        fprintf(ctest->logfile, "%s\n", d);
    }
    fifo_check_len(fifo);
    sw_set_unread(fifo);
    if (term) redraw_later();
}

void fifo_addfq(struct fifo *fifo, char *m, ...){ 
    gchar *c, *d, *now;
    int l;
    va_list v;

    if (!fifo) return;
    
    va_start(v, m);
    c = g_strdup_vprintf(m, v);
    va_end(v);
    l = strlen(c);
    if (l>0 && c[l-1]=='\n') c[l-1]='\0';
    if (l>0 && c[l-1]=='\r') c[l-1]='\0';
    
    if (!fifo->withouttime){
        now = hour_min();
        d = g_strconcat(now, " ", c, NULL);
        g_free(now);
        g_free(c);
    }
    else{
        d=c;
    }
    
    g_ptr_array_add(fifo->items, d);
	fifo_check_len(fifo);
    if (term) redraw_later();
}

void log_addf(char *m, ...){ 
    gchar *c, *d, *now;
    va_list v;

    if (!glog) return;
    
    va_start(v, m);
    c = g_strdup_vprintf(m, v);
    va_end(v);
	z_strip_crlf(c);    
    now = hour_min();
    d = g_strconcat(now, " ", c, NULL);
    g_free(now);
    g_free(c);
    
    g_ptr_array_add(glog->items, d);
    if (ctest && ctest->logfile){
        fprintf(ctest->logfile, "%s\n", d);
    }
    fifo_check_len(glog);
    if (term) redraw_later();
}

void fifo_add_lines(struct fifo *fifo, char *data){
	long pos = 0;
	long len = strlen(data);
	int wt = fifo->withouttime;

	GString *gs = g_string_sized_new(1024);
	fifo->withouttime = 1;
    while(1){
        if (!zfile_mgets(gs, data, &pos, len, 0)) break;
		fifo_adds(fifo, gs->str);
	}
	g_string_free(gs, TRUE);
	fifo->withouttime = wt;
}

void log_draw(struct fifo *fifo){
    int i,index;
    gchar *c;

    fill_area(fifo->x, fifo->y, fifo->w, fifo->h, COL_BG);
    for (i=0;i<fifo->h; i++){
        index = fifo->items->len-fifo->h+i;
        if (index<0)
           c = "~"; 
        else
           c = (char*)g_ptr_array_index(fifo->items, index);
		
		if (c && strlen(c)>fifo->ho) 
	        print_text(fifo->x, fifo->y+i, fifo->w, c+fifo->ho, COL_NORM);
    }
    
}       


int save_fifo_to_file(struct fifo *fifo, gchar *filename){
    FILE *f;
    int i,ret;
    gchar *c;

    f = fopen(filename, "wt");
    if (!f){
        log_addf(VTEXT(T_CANT_WRITE_S), filename);
        return errno;
    }
    
    for (i=0; i<fifo->items->len; i++){
        c=g_ptr_array_index(fifo->items, i);
        ret = fprintf(f, "%s\n", c);
        if (ret!=strlen(c)+1) {
            log_addf(VTEXT(T_CANT_WRITE_S), filename);
            return errno;
        }
    }
    
    fclose(f);
    return 0;
    
}

int load_fifo_from_file(struct fifo *fifo, gchar *filename, int drop){
    FILE *f;
    GString *gs;
    gchar *c;


	f = fopen(filename, "rt");
    if (!f){
        log_addf(VTEXT(T_CANT_READ_S), filename);
        return errno;
    }
    
    if (drop) drop_fifo(fifo);
    sw_unset_unread(fifo);
    gs=g_string_sized_new(100);
    fifo->withouttime=1;

    while( (c=zfile_fgets(gs, f, 0)) != NULL){
        fifo_adds(fifo, c);
    }
    fifo->withouttime=0;
    
    g_string_free(gs, TRUE);
    sw_unset_unread(fifo);
    
    fclose(f);
    return 0;
}

int fifo_contains(struct fifo *fifo, char *needle){
	int i;
	for (i = fifo->items->len - 1; i >= 0; i--){
		char *c = (char*)g_ptr_array_index(fifo->items, i);
		if (strcmp(c, needle) == 0) return 1;
	}
	return 0;
}

char *fifo_call_under(struct fifo *fifo, int x, int y){
	int i1, i2, len;
	char call[25];

	int index = fifo->items->len - fifo->h + y;
	if (index < 0) return NULL;
	if (index >= fifo->items->len) return NULL;
	
	char *c = (char*)g_ptr_array_index(fifo->items, index);
	char *s = g_strdup(c);
	z_str_uc(s);

	len = strlen(s);
	for (i1 = x + fifo->ho; i1 >= 0 && i1 < len; i1--){
		if (s[i1] >= 'A' && s[i1] <= 'Z') continue;
		if (s[i1] >= '0' && s[i1] <= '9') continue;
		if (s[i1] == '-') continue;
		if (s[i1] == '/') continue;
		break;
	}
	i1++; // line cannot begin with call

	len = strlen(s);
	for (i2 = x+fifo->ho; i2 < len; i2++){
		if (s[i2] >= 'A' && s[i2] <= 'Z') continue;
		if (s[i2] >= '0' && s[i2] <= '9') continue;
		if (s[i2] == '-') continue;
		if (s[i2] == '/') continue;
		break;
	}
	if (i2 > i1 && i2 - i1 < 20){
		g_strlcpy(call, s + i1, Z_MIN(i2 - i1 + 1, 20));
		if (z_can_be_call(call, ZCBC_SLASH | ZCBC_MINUS)){
			g_free(s);
			return g_strdup(call);
		}
	}

	return NULL;
}

void fifo_message(void *itdata, void *menudata){
	if (!gses) return;

	struct subwin *sw = sw_raise_or_new(SWT_KST);
	sw_set_focus();
	sw->callunder = g_strdup(gses->callunder);
	sw_kst_message(itdata, sw);
}

void fifo_kst_info(void *itdata, void *menudata){
	if (!gses) return;

	struct subwin *sw = sw_raise_or_new(SWT_KST);
	sw_set_focus();
	sw->callunder = g_strdup(gses->callunder);
	sw_kst_info(itdata, sw);
}

#ifdef Z_HAVE_SDL
void fifo_kst_ac_info(void *itdata, void *menudata){
	if (!gses) return;

	struct subwin *sw = sw_raise_or_new(SWT_KST);
	sw_set_focus();
	sw->callunder = g_strdup(gses->callunder);
	sw_kst_ac_info(itdata, sw);
}
#endif



