/*
 *                            COPYRIGHT
 *
 *  cschem - modular/flexible schematics editor - libcschem (core library)
 *  Copyright (C) 2018 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., 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_ABSTRACT_H
#define CSCH_ABSTRACT_H

#include <stdio.h>

#include <genht/htip.h>
#include <genht/htsp.h>
#include <genht/htpp.h>

#include "libcschem/common_types.h"
#include "libcschem/attrib.h"
#include "TODO.h"

struct csch_abstract_s {
	htip_t aid2obj;    /* primary storage: global aid -> (csch_ahdr_t *) */
	htul_t uid2id;     /* UID -> object id (cache) */
	htsp_t nets;       /* netname -> csch_anet_t */
	htsp_t comps;      /* name -> csch_acomp_t */
	long next_aid;

	/* counters for unique names */
	struct {
		long wirenet, comp, port;
		long target_tmp; /* next id for temporary object created by the target plugin(s) - post-increment */
	} ucnt;

	/* compilation state */
	unsigned new_comps:1; /* set to 1 whe a new component is created */
	unsigned new_nets:1;  /* set to 1 whe a new net is created */
	unsigned new_ports:1; /* set to 1 whe a new port is created */
	csch_project_t *prj;  /* only during compilation */
	long view_id;         /* which view the abstract model is compiled for; only during compilation */
	htpp_t eng_transient; /* private data used during compilation by engines; typically set in the project_before hook and removed/freed in the project_after hook; key is a const char *cookie */
};

typedef enum csch_atype_e {
	CSCH_ATYPE_INVALID = 0,
	CSCH_ATYPE_NET,
	CSCH_ATYPE_BUSNET,
	CSCH_ATYPE_BUSCHAN,
	CSCH_ATYPE_PORT,
	CSCH_ATYPE_BUSPORT,
	CSCH_ATYPE_COMP,
	CSCH_ATYPE_HUB
} csch_atype_t;
const char *csch_atype_name(csch_atype_t type);


struct csch_ahdr_s {
	csch_atype_t type;
	csch_attribs_t attr;
	long aid;
	vtp0_t srcs;              /* list of pointers to concrete objects that were source to this abstract object */
	csch_abstract_t *abst;
	const char *ghost;        /* if not NULL, the given object is only an empty shell (got used once during the compilation, but was emptied later, probably merged into something else) */
	unsigned compiled:1;      /* already compiled, compiler should skip it */

	/* cached from attributes to speed up render */
	unsigned dnp:1;           /* attribute display/dnp: do not populate */
	unsigned omit:1;          /* attribute display/dnp: omit from export */
};

typedef struct csch_acomp_s csch_acomp_t;


/* type = CSCH_ATYPE_NET */
typedef struct csch_anet_s {
	csch_ahdr_t hdr;
	vtp0_t conns; /* a list of (csch_ahdr_t *) connections, ports and bus-ports */
	char *name;   /* unique name for the hash */

	unsigned no_uname:1; /* 1 if there is no user assigned net name */
	unsigned term_term:1; /* the net was created for a "hidden" terminal-terminal connection */

	/* cached from attributes: */
	const char *chan;
} csch_anet_t;


/* type = CSCH_ATYPE_BUSCHAN */
typedef struct csch_anet_s csch_abuschan_t;

/* type = CSCH_ATYPE_BUSNET */
typedef struct csch_abusnet_s {
	csch_ahdr_t hdr;
	htsp_t *chans; /* of (csch_abuschan_t *), key is ->chan */

	/* cached from attributes: */
	const char *name;
} csch_abus_t;

/* type = CSCH_ATYPE_PORT */
typedef struct csch_aport_s {
	csch_ahdr_t hdr;
	csch_acomp_t *parent;
	char *name;

	struct {
		csch_anet_t *net; /* net the port is connected to */
		/* TODO: bus */
	} conn;

	/* cached from attributes: */
	const char *chan;
} csch_aport_t;

/* type = CSCH_ATYPE_BUSPORT */
typedef struct csch_abusport_s {
	csch_ahdr_t hdr;
	csch_acomp_t *parent;

	/* cached from attributes: */
	const char *name;
	void *chan_rewrite;
} csch_abusport_t;

/* type = CSCH_ATYPE_COMP */
struct csch_acomp_s {
	csch_ahdr_t hdr;
	char *name;
	htsp_t ports;    /* of csch_aport_t, key is ->name */
	htsp_t busports; /* of csch_abusport_t, key is ->name */
};

/* type = CSCH_ATYPE_HUB */
typedef struct csch_ahub_s {
	csch_ahdr_t hdr;
} csch_ahub_t;


/*** abs ***/
void csch_abstract_init(csch_abstract_t *abs);
void csch_abstract_uninit(csch_abstract_t *abs);
void csch_abstract_dump(const csch_abstract_t *abs, FILE *f, const char *prefix);

/*** net ***/
csch_anet_t *csch_anet_get(csch_abstract_t *abs, const char *netname, int alloc, int set_no_uname);

/*** component and port ***/
csch_acomp_t *csch_acomp_get(csch_abstract_t *abs, const char *name, int alloc);
csch_aport_t *csch_aport_get(csch_abstract_t *abs, csch_acomp_t *comp, const char *name, int alloc);

#endif
