/*
 *                            COPYRIGHT
 *
 *  cschem - modular/flexible schematics editor - GUI
 *  Copyright (C) 2022 Tibor 'Igor2' Palinkas
 *
 *  (Supported by NLnet NGI0 PET Fund in 2022)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *  Contact:
 *    Project page: http://repo.hu/projects/sch-rnd
 *    contact lead developer: http://www.repo.hu/projects/sch-rnd/contact.html
 *    mailing list: http://www.repo.hu/projects/sch-rnd/contact.html
 */

/* quick-edit attribute: symbol connect list */

#include <ctype.h>

#include <librnd/hid/hid_dad.h>
#include <librnd/hid/hid_dad_tree.h>

typedef struct {
	RND_DAD_DECL_NOINIT(dlg)
	csch_sheet_t *sheet;
	csch_cgrp_t *grp;
	int changed;
	int wlist, wadd, wsym, wnet;
} qa_connect_t;

static void qa_connect_close_cb(void *caller_data, rnd_hid_attr_ev_t ev)
{
	
}

static void qa_connect_sheet2dlg(qa_connect_t *ctx)
{
	rnd_hid_attribute_t *attr = &ctx->dlg[ctx->wlist];
	rnd_hid_tree_t *tree = attr->wdata;
	rnd_hid_row_t *r;
	char *cursor_path = NULL;
	const vts0_t *arr;

	/* remember cursor */
	r = rnd_dad_tree_get_selected(attr);
	if (r != NULL)
		cursor_path = rnd_strdup(r->cell[0]);

	/* remove existing items */
	rnd_dad_tree_clear(tree);

	/* add all items */
	arr = csch_attrib_get_arr(&ctx->grp->attr, "connect");
	if (arr != NULL) {
		long n;
		char *cell[3];

		cell[2] = NULL;
		for(n = 0; n < arr->used; n++) {
			char *c, *sep;
			int found = 0;

			c = arr->array[n];
			for(sep = c; *sep != '\0'; sep++) {
				if (sep[0] == ':') {
					found = 1;
					break;
				}
			}
			if (found) {
				cell[0] = rnd_strndup(c, sep-c);
				cell[1] = rnd_strdup(sep+1);
			}
			else {
				cell[0] = rnd_strdup(c);
				cell[1] = NULL;
			}
			rnd_dad_tree_append(attr, NULL, cell);
		}
	}

	/* restore cursor */
	if (cursor_path != NULL) {
		rnd_hid_attr_val_t hv;
		hv.str = cursor_path;
		rnd_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wlist, &hv);
		free(cursor_path);
	}
}

static void qa_connect_select_cb(rnd_hid_attribute_t *attrib, void *hid_ctx, rnd_hid_row_t *row)
{
	rnd_hid_tree_t *tree = attrib->wdata;
	qa_connect_t *ctx = tree->user_ctx;

	if (row != NULL) {
		rnd_hid_attr_val_t hv;

		hv.str = row->cell[0];
		rnd_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wsym, &hv);
		hv.str = row->cell[1];
		rnd_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wnet, &hv);
	}
}

static long sym2idx(qa_connect_t *ctx, long *totlen, int err)
{
	const vts0_t *arr = csch_attrib_get_arr(&ctx->grp->attr, "connect");
	long n, len;
	const char *sym = ctx->dlg[ctx->wsym].val.str, *end;

	if (totlen != NULL) {
		if (arr == NULL)
			*totlen = 0;
		else
			*totlen = arr->used;
	}

	if (sym != NULL)
		while(isspace(*sym)) sym++;

	if (((sym == NULL) || (*sym == '\0')) && err) {
		rnd_message(RND_MSG_ERROR, "Please fill in the symbol side name\n");
		return -1;
	}

	if ((arr == NULL) || (sym == NULL) || (*sym == '\0'))
		return -1;

	end = strpbrk(sym, " \t\r\n");
	if (end != NULL)
		len = end - sym;
	else
		len = strlen(sym);

	for(n = 0; n < arr->used; n++) {
		char *a = arr->array[n];
		if ((strncmp(a, sym, len) == 0) && (a[len] == ':'))
			return n;
	}

	if (err)
		rnd_message(RND_MSG_ERROR, "No entry found for symbol side name '%s'\n", sym);

	return -1;
}

static void qa_connect_del_cb(void *hid_ctx, void *caller_data, rnd_hid_attribute_t *attr)
{
	qa_connect_t *ctx = caller_data;
	long idx = sym2idx(ctx, NULL, 1);
	if (idx < 0)
		return;
	csch_attr_arr_modify_del(ctx->sheet, ctx->grp, "connect", idx, 1);
	qa_connect_sheet2dlg(ctx);
}

static void qa_connect_add_cb(void *hid_ctx, void *caller_data, rnd_hid_attribute_t *attr)
{
	qa_connect_t *ctx = caller_data;
	long totlen, idx = sym2idx(ctx, &totlen, 0);
	const char *sym = ctx->dlg[ctx->wsym].val.str;
	const char *net = ctx->dlg[ctx->wnet].val.str;
	gds_t tmp = {0};

	if ((sym == NULL) || (*sym == '\0') || (net == NULL) || (*net == '\0')) {
		rnd_message(RND_MSG_ERROR, "Please fill in both symbol and terminal side names first!\n");
		return;
	}

	gds_append_str(&tmp, sym);
	gds_append_str(&tmp, ":");
	gds_append_str(&tmp, net);

	if (idx >= 0)
		csch_attr_arr_modify_str(ctx->sheet, ctx->grp, "connect", idx, tmp.array, 1);
	else
		csch_attr_arr_modify_ins_before(ctx->sheet, ctx->grp, "connect", totlen, tmp.array, 1);

	qa_connect_sheet2dlg(ctx);
	gds_uninit(&tmp);
}

const char csch_acts_quick_attr_connect[] = "quick_attr_connect(objptr)";
const char csch_acth_quick_attr_connect[] = "Quick Attribute Edit for core data model's symbol connect attribute (attribute based symbol terminal to network connection table)";
fgw_error_t csch_act_quick_attr_connect(fgw_arg_t *res, int argc, fgw_arg_t *argv)
{
	qa_connect_t ctx = {0};
	rnd_design_t *hidlib = RND_ACT_DESIGN;
	rnd_hid_dad_buttons_t clbtn[] = {{"Close", 1}, {NULL, 0}};
	const char *hdr[] = {"Symbol term name", "Network name", NULL};

	ctx.sheet = (csch_sheet_t *)hidlib;
	ctx.changed = 0;
	QUICK_ATTR_GET_GRP(ctx.grp, "quick_attr_connect");

	RND_DAD_BEGIN_VBOX(ctx.dlg);
		RND_DAD_COMPFLAG(ctx.dlg, RND_HATF_EXPFILL);
		RND_DAD_TREE(ctx.dlg, 2, 0, hdr);
			RND_DAD_COMPFLAG(ctx.dlg, RND_HATF_EXPFILL | RND_HATF_SCROLL);
			ctx.wlist = RND_DAD_CURRENT(ctx.dlg);
			RND_DAD_TREE_SET_CB(ctx.dlg, selected_cb, qa_connect_select_cb);
			RND_DAD_TREE_SET_CB(ctx.dlg, ctx, &ctx);
		RND_DAD_BEGIN_HBOX(ctx.dlg);
			RND_DAD_LABEL(ctx.dlg, "Symbol term name:");
			RND_DAD_STRING(ctx.dlg);
				ctx.wsym = RND_DAD_CURRENT(ctx.dlg);
			RND_DAD_BUTTON(ctx.dlg, "Del");
				RND_DAD_CHANGE_CB(ctx.dlg, qa_connect_del_cb);
		RND_DAD_END(ctx.dlg);
		RND_DAD_BEGIN_HBOX(ctx.dlg);
			RND_DAD_LABEL(ctx.dlg, "Network name:");
			RND_DAD_STRING(ctx.dlg);
				ctx.wnet = RND_DAD_CURRENT(ctx.dlg);
			RND_DAD_BUTTON(ctx.dlg, "Add/edit");
				ctx.wadd = RND_DAD_CURRENT(ctx.dlg);
				RND_DAD_CHANGE_CB(ctx.dlg, qa_connect_add_cb);
		RND_DAD_END(ctx.dlg);
		RND_DAD_BUTTON_CLOSES(ctx.dlg, clbtn);
	RND_DAD_END(ctx.dlg);

	RND_DAD_NEW("quick_attr_connect", ctx.dlg, "Set symbol connect list", &ctx, 1, qa_connect_close_cb); /* type=local/modal */
	qa_connect_sheet2dlg(&ctx);
	RND_DAD_RUN(ctx.dlg);

	RND_ACT_IRES(ctx.changed);

	return 0;
}
