/*
 *                            COPYRIGHT
 *
 *  sch-rnd - modular/flexible schematics editor - GUI - quick attribute edit dialog
 *  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., 31 Milk Street, # 960789 Boston, MA 02196 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 attributes */

#include <libcschem/config.h>

#include <ctype.h>

#include <genvector/gds_char.h>
#include <librnd/core/actions.h>
#include <librnd/hid/hid_dad.h>
#include <librnd/hid/hid_dad_tree.h>
#include <libcschem/actions_csch.h>

#include "dlg_attrib.h"
#include "quick_attr.h"
#include "quick_attr_util.h"

static gds_t key2act_tmp = {0};

static const char *key2act(const char *key)
{
	int n;

	if (key2act_tmp.used == 0)
		gds_append_str(&key2act_tmp, "quick_attr_");
	else
		key2act_tmp.used = 11;

	gds_append_str(&key2act_tmp, key);

	/* replace non-alnum and non-underscore with __ */
	for(n = 0; n < key2act_tmp.used; n++) {
		int c = key2act_tmp.array[n];
		if (isalnum(c) || (c == '_'))
			continue;
		key2act_tmp.array[n] = '_';
		gds_insert_len(&key2act_tmp, n, "_", 1);
		n++;
	}

	return key2act_tmp.array;
}

int sch_rnd_attr_quick_editable(csch_sheet_t *sheet, csch_chdr_t *obj, const char *key)
{
	const char *name = key2act(key);
	const fgw_func_t *act = rnd_act_lookup(name);

	return (act != NULL);
}


int sch_rnd_attr_quick_edit(csch_sheet_t *sheet, csch_chdr_t *obj, const char *key)
{
	const char *name = key2act(key);
	fgw_func_t *ffgw = NULL;
	fgw_arg_t res = {0}, args[3];
	int ret;

	rnd_find_action(name, &ffgw);
	if (ffgw == NULL)
		return -1;


	fgw_ptr_reg(&rnd_fgw, &args[1], CSCH_PTR_DOMAIN_COBJ, FGW_PTR | FGW_STRUCT, (void *)obj);
	args[2].type = FGW_STR;
	args[2].val.cstr = key;
	ret = rnd_actionv_bin(&sheet->hidlib, name, &res, 3, args);
	fgw_ptr_unreg(&rnd_fgw, &args[1], CSCH_PTR_DOMAIN_COBJ);
	if (ret != 0)
		return -1;

	fgw_arg_conv(&rnd_fgw, &res, FGW_INT);
	return res.val.nat_int;
}

/*** stock quick edits (core data model) ***/

const char csch_acts_quick_attr_role[] = "quick_attr_role(objptr)";
const char csch_acth_quick_attr_role[] = "Quick Attribute Edit for core data model's role attribute";
fgw_error_t csch_act_quick_attr_role(fgw_arg_t *res, int argc, fgw_arg_t *argv)
{
	RND_DAD_DECL(dlg)
	rnd_design_t *hidlib = RND_ACT_DESIGN;
	csch_sheet_t *sheet = (csch_sheet_t *)hidlib;
	csch_cgrp_t *grp;
	const char *roles[] = {"<empty>", "bus-net", "bus-terminal", "hub-point", "symbol", "terminal", "wire-net", "junction", NULL};
	rnd_hid_dad_buttons_t clbtn[] = {{"Cancel", 0}, {"Ok", 1}, {NULL, 0}};
	int dres, wenum, orig;

	QUICK_ATTR_GET_GRP(grp, "quick_attr_role");
	orig = grp->role - 1;

	RND_DAD_BEGIN_VBOX(dlg);
		RND_DAD_LABEL(dlg, "Select new group role:");
		RND_DAD_ENUM(dlg, roles);
			RND_DAD_DEFAULT_NUM(dlg, orig);
			wenum = RND_DAD_CURRENT(dlg);
		RND_DAD_BUTTON_CLOSES(dlg, clbtn);
	RND_DAD_END(dlg);

	RND_DAD_AUTORUN("quick_attr_role", dlg, "Set group role", NULL, dres);

	RND_ACT_IRES(0);
	if ((dres == 1) && (dlg[wenum].val.lng) != orig) {
		csch_source_arg_t *src;
		const char *val = ((dlg[wenum].val.lng == 0) ? "" : roles[dlg[wenum].val.lng]);

		src = csch_attrib_src_c(NULL, 0, 0, "quick_attr_role user input");
		csch_attr_modify_str(sheet, grp, -CSCH_ATP_USER_DEFAULT, "role", val, src, 1);
		RND_ACT_IRES(1);
	}
	return 0;
}

const char csch_acts_QuickAttr[] = "QuickAttr(last-click|parent|object[:idpath], key)";
const char csch_acth_QuickAttr[] = "Quick Attribute Edit on key";
const char csch_acts_QuickAttrEditable[] = "QuickAttrEditable(last-click|parent|object[:idpath], key)";
const char csch_acth_QuickAttrEditable[] = "Returns 1 if obj:key has a quick attribute edit";
fgw_error_t csch_act_QuickAttr(fgw_arg_t *res, int argc, fgw_arg_t *argv)
{
	rnd_design_t *hidlib = RND_ACT_DESIGN;
	csch_sheet_t *sheet = (csch_sheet_t *)hidlib;
	const char *cmd, *key, *fname;
	csch_chdr_t *obj;
	int ret = -1, has_coords, check;

	fname = argv[0].val.argv0.func->name;
	check = (fname[9] == 'e') || (fname[9] == 'E');

	RND_ACT_CONVARG(1, FGW_STR, QuickAttr, cmd = argv[1].val.str);
	RND_ACT_CONVARG(2, FGW_STR, QuickAttr, key = argv[2].val.str);

	obj = sch_dialog_resolve_obj(sheet, "QuickAttr", cmd, &has_coords);
	if (obj != NULL) {
		if (check)
			ret = sch_rnd_attr_quick_editable(obj->sheet, obj, key);
		else
			ret = sch_rnd_attr_quick_edit(sheet, obj, key);
	}

	RND_ACT_IRES(ret);
	return 0;
}

/*** plugin administration ***/

void sch_rnd_attr_quick_uninit(void)
{
	gds_uninit(&key2act_tmp);
}
