/*
    translate.h - Localisation tool for Tucnak
    Copyright (C) 2015-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 "translate.h"

#include "bfu.h"
#include "fifo.h"
#include "main.h"
#include "menu.h"
#include "subwin.h"

char translate_key[MAX_STR_LEN];
char translate_oldkey[MAX_STR_LEN];
char translate_text[MAX_STR_LEN];
GPtrArray *translate_intl;
char *translate_c_file, *translate_lng_file;
GPtrArray *translate_lines;
int translate_line, translate_start, translate_len;


struct intl{
	char *key, *val;
};

void translate_replace(GString *line, char *newtext){
	g_string_erase(line, translate_start, translate_len);
	g_string_insert(line, translate_start, newtext);
}

char *translate_get_val(char *key){
	int i;

	for (i = 0; i < translate_intl->len; i++){
		struct intl *x = (struct intl *)g_ptr_array_index(translate_intl, i);
		if (strcmp(key, x->key) == 0) return x->val;
	}
	return NULL;
}

char *translate_get_key(char *val){
	int i;

	for (i = 0; i < translate_intl->len; i++){
		struct intl *x = (struct intl *)g_ptr_array_index(translate_intl, i);
		if (strcmp(val, x->val) == 0) return x->key;
	}
	return NULL;
}

void translate_free_intl(gpointer xxx){
	struct intl *x = (struct intl*) xxx;
	g_free(x->key);
	g_free(x->val);
	g_free(x);
}

int translate_load_intl(void){
	GString *gs;
	FILE *f;

	g_free(translate_lng_file);
	translate_lng_file = g_strdup("../intl/english.lng");
	z_wokna(translate_lng_file);
	f = fopen(translate_lng_file, "rt");
	if (!f) {
		zinternal("Can't open '%s'", translate_lng_file);
		return 0;
	}

	if (translate_intl != NULL) g_ptr_array_free(translate_intl, TRUE);
			
	translate_intl = g_ptr_array_new();
	g_ptr_array_set_free_func(translate_intl, translate_free_intl);
	
	gs = g_string_sized_new(256);
	while(zfile_fgets(gs, f, 0)){
		char *k, *v;
		struct intl *x;

		z_split2(gs->str, ',', &k, &v, 0);
		if (k == NULL) continue;

		if (v[0] == '"') v++;
		if (strlen(v) > 0 && v[strlen(v) - 1] == ',') v[strlen(v) - 1] = '\0';
		if (strlen(v) > 0 && v[strlen(v) - 1] == '"') v[strlen(v) - 1] = '\0';

		dbg("'%s'='%s'\n", k, v);
		x = g_new0(struct intl, 1);
		x->key = g_strdup(k);
		x->val = g_strdup(v);
		g_ptr_array_add(translate_intl, x);
	}

	g_string_free(gs, TRUE);
	fclose(f);
	return 0;
}

int translate_parse_file(const char *dir, const char *filename){
	FILE *f;
	GString *gsval, *gskey, *gsline;
	int ret = 0, i, j, bs = 0, ctext = 0;
	char *c, *line, *d, *dupkey, *dupval;

	g_free(translate_c_file);
	translate_c_file = g_strdup_printf("%s%s", dir, filename);

	f = fopen(translate_c_file, "rt");
	if (f == NULL) return 0;

	if (translate_lines != NULL) zg_ptr_array_free_all(translate_lines);
	translate_lines = g_ptr_array_new();
	gsval = g_string_sized_new(256);
	gskey = g_string_sized_new(256);
	while(zfile_fgets(gsval, f, 0)){
		g_ptr_array_add(translate_lines, g_strdup(gsval->str));		
	}
	fclose(f);

	for (i = 0; i < translate_lines->len; i++){
		line = (char*)g_ptr_array_index(translate_lines, i);
		c = strstr(line, "TRANSLATE(");
		if (c == NULL) continue;

		translate_line = i;
		translate_start = (c - line);
		log_adds("");
		log_adds("");
		log_addf("      -------- %s --------", filename);
		for (j = Z_MAX(i - 5, 0); j < Z_MIN(i + 5, translate_lines->len - 1); j++) {
			g_string_truncate(gsval, 0);
			g_string_append(gsval, (char *)g_ptr_array_index(translate_lines, j));
			z_string_replace(gsval, "\x09", "    ", ZSR_ALL);
			log_addf("%4d: %s", j, gsval->str);
		}

		g_string_truncate(gsval, 0);
		g_string_append(gsval, c + 11);

		for (j = 0; j < gsval->len; j++){
			if (gsval->str[j] == '"' && bs == 0){
				g_string_truncate(gsval, j);
				translate_len = j + 11 + 2;
				break;
			}
			if (gsval->str[j] == '\\'){
				bs = 1;
			}else{
				bs = 0;
			}
		}
		
		for (d = gsval->str; *d != '\0'; d++){
			char cc = *d;
			if (cc == ' ') cc = '_';
			if (isalnum(cc) || cc == '_'){
				g_string_append_c(gskey, toupper(cc));
			}
		}
		while (gskey->len > 0 && gskey->str[0] == '_') g_string_erase(gskey, 0, 1);
		while (gskey->len > 0 && gskey->str[gskey->len - 1] == '_') g_string_erase(gskey, gskey->len - 1, 1);
		g_string_insert(gskey, 0, "T_");
		

		dupkey = translate_get_key(gsval->str);
		if (dupkey != NULL){
			g_string_assign(gskey, dupkey);
		}else{
			for (j = 1; ; j++){
				char *tmp;
				if (j == 1)
					tmp = g_strdup(gskey->str);
				else
					tmp = g_strdup_printf("%s%d", gskey->str, j);

				dupval = translate_get_val(tmp);
				g_free(tmp);
				if (dupval != NULL) 
					continue;
				if (j == 1) break;
				g_string_append_printf(gskey, "%d", j);
				break;
			}
		}

		if (strstr(line, "add_to_menu")) ctext = 1;
		if (strstr(line, "input_field")) ctext = 1;
		if (strstr(line, "{TRANSLATE")) ctext = 1;
		if (strstr(line, "{CTEXT")) ctext = 1;
		if (strstr(line, "d->items[i].")) ctext = 1;
		//if (strstr(line, "")) ctext = 1;
		//if (strstr(line, "")) ctext = 1;
		


		
		g_snprintf(translate_key, MAX_STR_LEN, "%cTEXT(%s)", ctext ? 'C' : 'V', gskey->str);
		strcpy(translate_oldkey, translate_key);
		g_snprintf(translate_text, MAX_STR_LEN, "%s", gsval->str);

		log_addf("line %d, start=%d, len=%d", translate_line, translate_start, translate_len);
		gsline = g_string_new(line);
		translate_replace(gsline, translate_key);
		z_string_replace(gsline, "\x09", "    ", ZSR_ALL);
		log_addf("%4d: %s", i, gsline->str);
		ret = 1;
		break;
	}
	

	g_string_free(gsval, TRUE);
	g_string_free(gskey, TRUE);
	//zg_ptr_array_free_all(arr);
	return ret;
}

static int translate_filter(const char *dir, const struct dirent *de){
	const char *ext;

    if (strcmp((char *)de->d_name, ".") == 0) return 0;
    if (strcmp((char *)de->d_name, "..") == 0) return 0;

	ext = z_extension((char *)de->d_name);
	if (ext == NULL) return 0;
	
	if (strcmp(ext, ".c") == 0) return 1;
	return 0;
}

void translate_save_c(void){
	int i;
	FILE *f = fopen(translate_c_file, "wb");
	if (!f) zinternal("Can't open %s", translate_c_file);

	for (i = 0; i < translate_lines->len; i++){
		GString *gs = NULL;
		char *line = (char *)g_ptr_array_index(translate_lines, i);
		if (i == translate_line){
			gs = g_string_new(line);
			translate_replace(gs, translate_key);
			line = gs->str;
		}
		fprintf(f, "%s\n", line);
		if (gs) g_string_free(gs, TRUE);
	}
	fclose(f);
}

int translate_save_lng(void){
	char *k, *c, *lng_text;
	FILE *f;

	k = g_strdup(translate_key);
	c = strchr(k, '(');
	if (!c) zinternal("No '(' in translate_key");
	c++;
	z_strip_from(c, ')');

	lng_text = translate_get_val(c);
	if (lng_text) {
		// exists same key in the lng database
		if (strcmp(translate_text, lng_text) == 0){
			// user entered same text as in db
			log_addf("Merging to key '%s'", c);
			return 0; // change the c file
		}else{
			// user entered different text than in db
			//if (strcmp(translate_key, translate_oldkey) == 0){
			//	// but same key, error
			    log_addf("----------------------------------------------------------------------");
				log_addf("  Key '%s' already exists in lng file with different text", c);
			    log_addf("----------------------------------------------------------------------");
				return 1; // do not change the c file
			//}else{
			//	// different text and different key, no problem bro
			//
			//}
		}
	}

	f = fopen(translate_lng_file, "ab");
	if (!f) zinternal("Can't open %s", translate_lng_file);
	fprintf(f, "%s, \"%s\",\n", c, translate_text);
	g_free(k);
	
	fclose(f);
	return 0;
}

void refresh_translate(void *xxx){
    struct dirent **namelist=NULL;
	int i;
	int nn;
	char dir[256];

	translate_load_intl();

	if (strlen(translate_key) != 0){
		if (translate_save_lng() == 0){
			translate_save_c();
		}
	}

	translate_load_intl();


	strcpy(dir, "../src/");
    z_wokna(dir);

	nn = z_scandir(dir, &namelist, translate_filter, z_scandir_alphasort);
	for (i=0; i<nn; i++){
		if (strcmp(namelist[i]->d_name, "translate.c") == 0) continue;
		if (translate_parse_file(dir, namelist[i]->d_name)) break;
	}

    for (i=0; i<nn; i++) free(namelist[i]);
    free(namelist);
	zselect_bh_new(zsel, translate, NULL);
}

void translate_fn3(struct dialog_data *dlgd){
	dlgd->y = 0;
}

void translate(void *xxx){
    struct dialog *d;
    int i;

	sw_raise_or_new(SWT_LOG);

	d = (struct dialog *)g_malloc(sizeof(struct dialog) + 20 * sizeof(struct dialog_item));
    memset(d, 0, sizeof(struct dialog) + 20 * sizeof(struct dialog_item));
    d->title = "Translate"; 
    d->fn = dlg_pf_fn;
	d->position_fn = translate_fn3;
    d->refresh = (void (*)(void *))refresh_translate;
    d->y0 = 1;

	d->items[i = 0].type = D_FIELD;      
    d->items[i].gid = 0;
    d->items[i].gnum = 1;
    d->items[i].dlen = MAX_STR_LEN;
    d->items[i].data = (char *)&translate_key;
    d->items[i].msg = "Key: ";
    d->items[i].wrap = 1;

	d->items[++i].type = D_FIELD;      
    d->items[i].gid = 0;
    d->items[i].gnum = 1;
    d->items[i].dlen = MAX_STR_LEN;
    d->items[i].data = (char *)&translate_text;
    d->items[i].msg = "Text:";
    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;
	
	set_window_ptr(gses->win, 0, 0);
    do_dialog(d, getml(d, NULL));

}
