/*
 *                            COPYRIGHT
 *
 *  cschem - modular/flexible schematics editor - libcschem (core library)
 *  Copyright (C) 2023 Tibor 'Igor2' Palinkas
 *
 *  (Supported by NLnet NGI0 Entrust Fund 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., 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
 */


#ifndef CSCH_PROJECT_P4_H
#define CSCH_PROJECT_P4_H

/* Per Plugin Per Project (p4) data */

#include <libcschem/project.h>

typedef long csch_p4id_t; /* used internally for indexing project->p4data */

typedef struct csch_p4cfg_s csch_p4cfg_t;
struct csch_p4cfg_s {

	/* called early in project creation; plugin should allocate
	   p4 data and store it in the project. prj fields are not initialized
	   yet. Also called on csch_p4_reg_plugin() for all projects */
	void (*project_init)(csch_p4cfg_t *p4, csch_project_t *prj);

	/* called while a project is discarded (no sheet loaded anymore); plugin
	   should free p4 data still stored in the project. Also called on
	   csch_p4_unreg_plugin() for all projects. Libcschem sets project's p4
	   data to NULL after this call. */
	void (*project_uninit)(csch_p4cfg_t *p4, csch_project_t *prj);

	/* as assigned on registration, filled in by libcschem; used for
	   indexing project->p4data */
	csch_p4id_t id;

	/* opqaue data for the registration (not plugin-specific); only the
	   plugin uses this */
	void *plugin_data;
};

/* Register a plugin by its p4cfg; id is filled in here; cfg->project_init
   is called for all existing projects */
void csch_p4_reg_plugin(csch_p4cfg_t *cfg);

/* Unregister a plugin by its p4cfg; id is reset to -1; cfg->project_uninit
   is called for all existing projects */
void csch_p4_unreg_plugin(csch_p4cfg_t *cfg);

/* Store p4 data in a project, overwriting previous data. p4 data
   is a void * allocated by the plugin. It's typically allocated and
   stored in the ->project_init() callback and free'd in the
   ->project_uninit() callback */
void csch_p4_set_by_project(csch_p4cfg_t *cfg, csch_project_t *prj, void *data);


/* Return the plugin's p4 data for a project or a sheet (or NULL if not
   available). When not NULL, data had been previously registered by the
   plugin using csch_p4_set_(). */
RND_INLINE void *csch_p4_get_by_project(csch_p4cfg_t *cfg, csch_project_t *prj);
RND_INLINE void *csch_p4_get_by_sheet(csch_p4cfg_t *cfg, csch_sheet_t *sheet);

/*** Internal calls for libcschem ***/

/* Call all p4 ->project_init or ->project_uninit of all p4 plugins */
void csch_p4_call_project_init(csch_project_t *prj);
void csch_p4_call_project_uninit(csch_project_t *prj);

/*** Implementation ***/

RND_INLINE void *csch_p4_get_by_project(csch_p4cfg_t *cfg, csch_project_t *prj)
{
	if ((cfg->id < 0) || (cfg->id >= prj->p4data.used))
		return NULL;

	return prj->p4data.array[cfg->id];
}

RND_INLINE void *csch_p4_get_by_sheet(csch_p4cfg_t *cfg, csch_sheet_t *sheet)
{
	return csch_p4_get_by_project(cfg, (csch_project_t *)sheet->hidlib.project);
}

/*** For internal use ***/
void csch_p4_uninit(void);

#endif
