/*
 *                            COPYRIGHT
 *
 *  sch-rnd - modular/flexible schematics editor - sch-rnd (executable)
 *  Copyright (C) 2020,2023 Tibor 'Igor2' Palinkas
 *
 *  (Supported by NLnet NGI0 Entrust in 2023)
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.*
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; 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
 */

#include "config.h"

#include <librnd/config.h>

#include <librnd/core/actions.h>
#include <librnd/core/compat_misc.h>
#include <librnd/core/conf.h>
#include <libcschem/event.h>
#include <libcschem/project.h>
#include <libcschem/plug_io.h>
#include <libcschem/cnc_text.h>


#include <sch-rnd/multi.h>
#include <sch-rnd/project.h>

#include "plug_io_act.h"

static const char *plug_io_cookie = "plug_io_act";

static const char csch_acts_LoadFrom[] = "LoadFrom(Sheet|Project,filename[,format])";
static const char csch_acth_LoadFrom[] = "Load project or sheet data from a file.";
fgw_error_t csch_act_LoadFrom(fgw_arg_t *res, int argc, fgw_arg_t *argv)
{
	const char *op, *name, *format = NULL;

	RND_ACT_CONVARG(1, FGW_STR, LoadFrom, op = argv[1].val.str);
	RND_ACT_CONVARG(2, FGW_STR, LoadFrom, name = argv[2].val.str);
	RND_ACT_MAY_CONVARG(3, FGW_STR, LoadFrom, format = argv[3].val.str);

	if (rnd_strcasecmp(op, "sheet") == 0) {
		csch_sheet_t *sheet;
		rnd_design_t *last;

		last = rnd_multi_switch_to(NULL); /* empty conf so we can overwrite */
		sheet = sch_rnd_multi_load(name, format, NULL);
		if (sheet == NULL) {
			rnd_multi_switch_to_(last); /* go back to last */
			rnd_message(RND_MSG_ERROR, "Can not load file '%s'\n", name);
			RND_ACT_IRES(-1);
			return 0;
		}
		rnd_multi_switch_to_(&sheet->hidlib); /* activate new */
	}
	else if (rnd_strcasecmp(op, "project") == 0) {
		TODO("the actual project load");
		rnd_message(RND_MSG_ERROR, "LoadFrom(project,...) not yet implemented\n");
	}
	else
		RND_ACT_FAIL(LoadFrom);

	RND_ACT_IRES(0);
	return 0;
}

static const char csch_acts_Unload[] = "Unload(Sheet|Project)";
static const char csch_acth_Unload[] = "Unload (close) current project or sheet";
fgw_error_t csch_act_Unload(fgw_arg_t *res, int argc, fgw_arg_t *argv)
{
	const char *op;

	RND_ACT_CONVARG(1, FGW_STR, Unload, op = argv[1].val.str);

	if (rnd_strcasecmp(op, "sheet") == 0) {
		rnd_design_t *dsg = rnd_multi_get_current();
		csch_sheet_t *next = (csch_sheet_t *)rnd_multi_neighbour_sheet(NULL);

		rnd_event(dsg, CSCH_EVENT_SHEET_PREUNLOAD, NULL);

		sch_rnd_multi_unload((csch_sheet_t *)dsg);
		if (next == NULL) {
			/* unloaded the last sheet */
			exit(1);
		}

		rnd_event(&next->hidlib, CSCH_EVENT_SHEET_POSTUNLOAD, NULL);
		rnd_multi_switch_to(&next->hidlib); /* activate new */
	}
	else if (rnd_strcasecmp(op, "project") == 0) {
		TODO("the actual project load");
		rnd_message(RND_MSG_ERROR, "Unload(project,...) not yet implemented\n");
	}
	else
		RND_ACT_FAIL(Unload);

	RND_ACT_IRES(0);
	return 0;
}

TODO("librnd 4.5: see below")
extern lht_doc_t *rnd_conf_main_root[RND_CFR_max_alloc];

static const char csch_acts_SaveTo[] = "SaveTo(Sheet|Project,filename[,format])";
static const char csch_acth_SaveTo[] = "Save project or sheet to a file.";
fgw_error_t csch_act_SaveTo(fgw_arg_t *res, int argc, fgw_arg_t *argv)
{
	const char *op, *name, *format = "lihata";
	csch_sheet_t *sheet = CSCH_ACT_SHEET;
	int renamed;

	RND_ACT_CONVARG(1, FGW_STR, SaveTo, op = argv[1].val.str);
	RND_ACT_CONVARG(2, FGW_STR, SaveTo, name = argv[2].val.str);
	RND_ACT_MAY_CONVARG(3, FGW_STR, SaveTo, format = argv[3].val.str);

	if (rnd_strcasecmp(op, "sheet") == 0) {
		renamed = ((sheet->hidlib.fullpath == NULL) || (strcmp(name, sheet->hidlib.fullpath) != 0));
		if (csch_save_sheet(sheet, name, format) != 0) {
			rnd_message(RND_MSG_ERROR, "Can not save file '%s'\n", name);
			RND_ACT_IRES(-1);
			return 0;
		}
		if (renamed) {
			{ /* load new project file */
				const char *try, *fn = rnd_conf_get_project_conf_name(NULL, sheet->hidlib.fullpath, &try);
				csch_project_t *new_prj;

				sch_rnd_multi_switch_to(NULL); /* make sure loading the new project doesn't interfere with the exisitng project, potentially in use by other sheets in multi */
				new_prj = sch_rnd_multi_load_project(sheet->hidlib.fullpath, fn);
				rnd_multi_switch_to_(&sheet->hidlib);

				if (&new_prj->hdr != sheet->hidlib.project) {
					if (fn == NULL)
						rnd_message(RND_MSG_INFO, "Project file changed (to non-existing) for sheet upon save-as into a different directory.\n");
					else
						rnd_message(RND_MSG_INFO, "Project file changed to '%s' for sheet upon save-as into a different directory.\n", fn);

					if (sch_rnd_prj_remove_sheet(sheet) > 0) {
						TODO("librnd 4.5: figure what to do with this:")
						/* need to set PROJECT dom to NULL so that loading a new doc won't
						   free the old, which is still in use by other sheets (in multi) */
						rnd_conf_main_root[RND_CFR_PROJECT] = NULL;
						rnd_project_append_design(&new_prj->hdr, &sheet->hidlib);
					}
					rnd_conf_load_as(RND_CFR_PROJECT, fn, 0);
					rnd_conf_merge_all(NULL);
					sch_rnd_prj_postproc(new_prj);

					/* get the GUI updated for the new conf (e.g. color) */
					rnd_event(&sheet->hidlib, RND_EVENT_DESIGN_SET_CURRENT_INTR, "p", &sheet->hidlib);
					rnd_event(&sheet->hidlib, RND_EVENT_DESIGN_SET_CURRENT, "p", &sheet->hidlib);
				}
			}

			/* invalidate dynamic text objects so that %project.name% is recalculated */
			csch_text_invalidate_all_sheet(sheet, 1);

			/* get sheetsel updated */
			rnd_event(&sheet->hidlib, RND_EVENT_DESIGN_META_CHANGED, NULL);
			rnd_event(&sheet->hidlib, RND_EVENT_DESIGN_FN_CHANGED, NULL);
		}
	}
	else if (rnd_strcasecmp(op, "project") == 0) {
		rnd_message(RND_MSG_ERROR, "SaveTo(project,...) not yet implemented\n");
	}
	else
		RND_ACT_FAIL(SaveTo);

	RND_ACT_IRES(0);
	return 0;
}

static rnd_action_t csch_plug_io_act_list[] = {
	{"SaveTo", csch_act_SaveTo, csch_acth_SaveTo, csch_acts_SaveTo},
	{"LoadFrom", csch_act_LoadFrom, csch_acth_LoadFrom, csch_acts_LoadFrom},
	{"Unload", csch_act_Unload, csch_acth_Unload, csch_acts_Unload},
};

void csch_plug_io_act_init(void)
{
	RND_REGISTER_ACTIONS(csch_plug_io_act_list, plug_io_cookie);
}

void csch_plug_io_act_uninit(void)
{
	rnd_remove_actions_by_cookie(plug_io_cookie);
}

