/*
 *                            COPYRIGHT
 *
 *  cschem - modular/flexible schematics editor - libcschem (core library)
 *  Copyright (C) 2019 Tibor 'Igor2' Palinkas
 *
 *  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
 */


#ifndef CSCH_ENGINE_H
#define CSCH_ENGINE_H

#include <librnd/core/config.h>
#include <librnd/core/actions.h>
#include <libcschem/common_types.h>
#include <libcschem/abstract.h>
#include <genht/htss.h>

typedef enum {
	CSCH_ENGHK_TERMINAL_NAME_TO_PORT_NAME,
	CSCH_ENGHK_WIRENET_NAME_TO_NET_NAME,
	CSCH_ENGHK_ATTRIB_NET_NAME_TO_NET_NAME,
	CSCH_ENGHK_SYMBOL_NAME_TO_COMPONENT_NAME,
	CSCH_ENGHK_SYMBOL_JOINED_COMPONENT,
	CSCH_ENGHK_COMPILE_COMPONENT0, /* called once per component, after all symbol merges, before port processing; should set component attributes but should not have any other side effect (e.g. making connections) */
	CSCH_ENGHK_COMPILE_COMPONENT1, /* same as component0, but can have side effects */
	CSCH_ENGHK_COMPILE_COMPONENT2, /* called once per component, after port merges finished */
	CSCH_ENGHK_COMPILE_PORT,
	CSCH_ENGHK_COMPILE_NET,
	CSCH_ENGHK_CONNS_BEFORE,  /* called once per sheet, before starting to compile connection objects */
	CSCH_ENGHK_CONNS_AFTER,   /* called once per sheet, after finished compiling connection objects */
	CSCH_ENGHK_PROJECT_BEFORE, /* called once before starting to compile the project */
	CSCH_ENGHK_PROJECT_AFTER, /* called once after finished compiling the project */
	CSCH_ENGHK_max
} csch_eng_hook_t;

struct csch_view_eng_s {
	fgw_obj_t *obj;
	htss_t cfg;

	/* cache */
	fgw_func_t *hook[CSCH_ENGHK_max]; /* look up all hooks once after load so calls don't have to go trhough */
	void *cfg_cache; /* optional: compiled by the engine */
	short int eprio; /* engine priority; final attribute priority should be (CSCH_PRI_PLUGIN_* + eprio) */
	char *options; /* parameter (e.g. script file name) specified on creation */
};

typedef struct csch_hook_call_ctx_s {
	csch_project_t *project;
	const csch_view_eng_t *view_eng;
	int view_id;
	csch_hier_path_t *hpath;
} csch_hook_call_ctx_t;

csch_view_eng_t *csch_eng_alloc(csch_view_t *view, const char *user_name, const char *eng_name, const char *options);
void csch_eng_free(csch_view_t *view, csch_view_eng_t *eng);

/* temporary until fungw C binding installation is sorted out */
fgw_error_t csch_c_call_script(fgw_arg_t *res, int argc, fgw_arg_t *argv);

/*** calls ***/

/* Call hooks, expect no reply; returns 0 on success, -1 on view or
   argument error */
int csch_eng_call(csch_project_t *proj, int viewid, csch_hier_path_t *hpath, csch_eng_hook_t hkid, ...);

/* Call hooks to modify a name. Result is in *res_glob and *res_loc after
   the call are strdup'd and can be freed using csch_eng_call_namemod(). If
   any of these are NULL, there was an internal error. */
void csch_eng_call_namemod(csch_project_t *proj, int viewid, csch_hier_path_t *hpath, csch_eng_hook_t hook, char **res_glob, char **res_loc, const char *defval, ...);

/* Clean up after csch_eng_call_namemod(). */
RND_INLINE void csch_eng_free_namemod(char **res_glob, char **res_loc);


/*** implementation ***/
RND_INLINE void csch_eng_free_namemod(char **res_glob, char **res_loc)
{
	free(*res_glob); res_glob = NULL;
	free(*res_loc);  res_loc = NULL;
}

#endif
