#include "event.h"
#include "hid_dad.h"

static const char pcb_acts_LayerPropGui[] = "LayerPropGui(layerid)";
static const char pcb_acth_LayerPropGui[] = "Change layer flags and properties";
static fgw_error_t pcb_act_LayerPropGui(fgw_arg_t *res, int argc, fgw_arg_t *argv)
{
	PCB_DAD_DECL(dlg)
	pcb_hid_dad_buttons_t clbtn[] = {{"Cancel", 0}, {"OK", 1}, {NULL, 0}};
	int wname, wsub, wauto, ok, ar = 0;
	pcb_layer_t *ly;
	pcb_layer_id_t lid;


	PCB_ACT_MAY_CONVARG(1, FGW_LONG, LayerPropGui, lid = argv[1].val.nat_long);
	ly = pcb_get_layer(PCB->Data, lid);

	PCB_DAD_BEGIN_VBOX(dlg);
		PCB_DAD_BEGIN_TABLE(dlg, 2);
			PCB_DAD_LABEL(dlg, "name");
			PCB_DAD_STRING(dlg);
				PCB_DAD_HELP(dlg, "logical layer name");
				wname = PCB_DAD_CURRENT(dlg);
			PCB_DAD_LABEL(dlg, "sub");
			PCB_DAD_BOOL(dlg, "");
				PCB_DAD_HELP(dlg, "Layer is drawn negatively in composition\n(will not work on copper)");
				wsub = PCB_DAD_CURRENT(dlg);
			PCB_DAD_LABEL(dlg, "auto");
			PCB_DAD_BOOL(dlg, "");
				PCB_DAD_HELP(dlg, "Layer is target for autogenerated objects\nand side effects, e.g. padstack shapes");
				wauto = PCB_DAD_CURRENT(dlg);
		PCB_DAD_END(dlg);
		PCB_DAD_BUTTON_CLOSES(dlg, clbtn);
	PCB_DAD_END(dlg);
	

	dlg[wname].default_val.str_value = pcb_strdup(ly->name);
	dlg[wsub].default_val.int_value = ly->comb & PCB_LYC_SUB;
	dlg[wauto].default_val.int_value = ly->comb & PCB_LYC_AUTO;

	PCB_DAD_AUTORUN("layer_prop", dlg, "Properties of a logical layer", NULL, ok);

	if (ok) {
		pcb_layer_combining_t comb = 0;
		if (strcmp(ly->name, dlg[wname].default_val.str_value) != 0) {
			ar |= pcb_layer_rename_(ly, (char *)dlg[wname].default_val.str_value);
			pcb_board_set_changed_flag(pcb_true);
		}
		if (dlg[wsub].default_val.int_value) comb |= PCB_LYC_SUB;
		if (dlg[wauto].default_val.int_value) comb |= PCB_LYC_AUTO;
		if (ly->comb != comb) {
			ly->comb = comb;
			pcb_board_set_changed_flag(pcb_true);
		}
	}
	else
		ar = 1;
	PCB_DAD_FREE(dlg);

	PCB_ACT_IRES(ar);
	return 0;
}

static const char pcb_acts_GroupPropGui[] = "GroupPropGui(groupid)";
static const char pcb_acth_GroupPropGui[] = "Change group flags and properties";
static fgw_error_t pcb_act_GroupPropGui(fgw_arg_t *res, int argc, fgw_arg_t *argv)
{
	PCB_DAD_DECL(dlg)
	pcb_hid_dad_buttons_t clbtn[] = {{"Cancel", 0}, {"OK", 1}, {NULL, 0}};
	int wname, wtype, wpurp, wloc;
	int ok, n, ar = 0, orig_type, changed = 0, omit_loc = 0, orig_loc = -1, def_loc;
	pcb_layergrp_id_t gid;
	pcb_layergrp_t *g;
	static const char *ltypes[] = { "top", "bottom", "any intern", "global", NULL };
	pcb_layer_type_t ltype_bits[] = { PCB_LYT_TOP, PCB_LYT_BOTTOM, PCB_LYT_INTERN, 0 };
#define LOC_TYPES (PCB_LYT_DOC)

	PCB_ACT_MAY_CONVARG(1, FGW_LONG, GroupPropGui, gid = argv[1].val.nat_long);
	g = pcb_get_layergrp(PCB, gid);

	if (g->ltype & LOC_TYPES) {
		for(n = 0; ltype_bits[n] != 0; n++)
			if (g->ltype & ltype_bits[n])
				def_loc = n;
	}
	else
		omit_loc = 1;

	PCB_DAD_BEGIN_VBOX(dlg);
		PCB_DAD_BEGIN_TABLE(dlg, 2);
			PCB_DAD_LABEL(dlg, "name");
			PCB_DAD_STRING(dlg);
				PCB_DAD_HELP(dlg, "group name");
				wname = PCB_DAD_CURRENT(dlg);
			PCB_DAD_LABEL(dlg, "type");
			PCB_DAD_ENUM(dlg, lb_types);
				PCB_DAD_HELP(dlg, "type/material of the group");
				wtype = PCB_DAD_CURRENT(dlg);
			if (!omit_loc) {
				PCB_DAD_LABEL(dlg, "location");
				PCB_DAD_ENUM(dlg, ltypes);
					PCB_DAD_HELP(dlg, "location of the group in the stack");
					wloc = PCB_DAD_CURRENT(dlg);
			}
			PCB_DAD_LABEL(dlg, "purpose");
			PCB_DAD_STRING(dlg);
				PCB_DAD_HELP(dlg, "purpose");
				wpurp = PCB_DAD_CURRENT(dlg);
				PCB_DAD_HELP(dlg, "subtype of the layer\nmeaning depends on the main type");
		PCB_DAD_END(dlg);
		PCB_DAD_BUTTON_CLOSES(dlg, clbtn);
	PCB_DAD_END(dlg);


	dlg[wname].default_val.str_value = pcb_strdup(g->name);
	dlg[wtype].default_val.int_value = orig_type = ly_type2enum(g->ltype);
	dlg[wpurp].default_val.str_value = pcb_strdup(g->purpose == NULL ? "" : g->purpose);
	if (!omit_loc)
		dlg[wloc].default_val.int_value = def_loc;

	if (!omit_loc) {
		pcb_layer_type_t loc = g->ltype & PCB_LYT_ANYWHERE;
		dlg[wloc].default_val.int_value = 3;
		if (loc != 0) {
			for(n = 0; ltypes[n] != NULL; n++) {
				if ((loc & ltype_bits[n]) == loc) {
					dlg[wloc].default_val.int_value = n;
					break;
				}
			}
		}
		orig_loc = dlg[wloc].default_val.int_value;
	}

	PCB_DAD_AUTORUN("layer_grp_prop", dlg, "Edit the properties of a layer group (physical layer)", NULL, ok);
	if (ok) {
		if (strcmp(g->name, dlg[wname].default_val.str_value) != 0) {
			ar |= pcb_layergrp_rename_(g, (char *)dlg[wname].default_val.str_value);
			dlg[wname].default_val.str_value = NULL;
			pcb_board_set_changed_flag(pcb_true);
		}

		if (dlg[wtype].default_val.int_value != orig_type) {
			pcb_layer_type_t lyt = 0;
			get_ly_type_(dlg[wtype].default_val.int_value, &lyt);
			g->ltype &= ~PCB_LYT_ANYTHING;
			g->ltype |= lyt;
			changed = 1;
		}

		if ((!omit_loc) && (dlg[wloc].default_val.int_value != orig_loc)) {
			if (PCB_LAYER_SIDED(g->ltype)) {
				g->ltype &= ~PCB_LYT_ANYWHERE;
				if (dlg[wloc].default_val.int_value >= 0)
					g->ltype |= ltype_bits[dlg[wloc].default_val.int_value];
				changed = 1;
			}
			else
				pcb_message(PCB_MSG_ERROR, "Ignoring location - for this layer group type it is determined by the stackup\n");
		}

		if (dlg[wpurp].default_val.str_value == NULL) {
			if (g->purpose != NULL) {
				pcb_layergrp_set_purpose__(g, NULL);
				changed = 1;
			}
		}
		else if ((g->purpose == NULL) || (strcmp(g->purpose, dlg[wpurp].default_val.str_value) != 0)) {
			if (*dlg[wpurp].default_val.str_value == '\0')
				pcb_layergrp_set_purpose__(g, NULL);
			else
				pcb_layergrp_set_purpose__(g, pcb_strdup(dlg[wpurp].default_val.str_value));
			changed = 1;
		}

		if (changed) {
			pcb_board_set_changed_flag(pcb_true);
			pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL);
		}
	}
	else
		ar = 1;

	PCB_DAD_FREE(dlg);

	PCB_ACT_IRES(ar);
	return 0;
}
#undef LOC_TYPES
