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

/* Utility functions for maintaining a local (per sheet) library */

#include "config.h"

#include <librnd/core/error.h>

#include <libcschem/concrete.h>
#include <libcschem/cnc_grp.h>

#include "util_loclib.h"

csch_cgrp_t *csch_loclib_get_root_by_name(csch_sheet_t *sheet, const char *name, csch_source_arg_t *src, int alloc, int *alloced)
{
	htip_entry_t *e;

	if (alloc)
		*alloced = 0;

	for(e = htip_first(&sheet->indirect.id2obj); e != NULL; e = htip_next(&sheet->indirect.id2obj, e)) {
		csch_cgrp_t *grp = e->value;
		const char *gpurp = csch_attrib_get_str(&grp->attr, "purpose");
		if ((gpurp != NULL) && (strcmp(gpurp, name) == 0)) {
			csch_attr_src_free(src);
			return grp;
		}
	}

	if (alloc) {
		csch_cgrp_t *grp = csch_cgrp_alloc(sheet, &sheet->indirect, csch_oid_new(sheet, &sheet->indirect));
		csch_attrib_set(&grp->attr, 0, "purpose", name, src, NULL);
		*alloced = 1;
		csch_sheet_set_changed(sheet, 1);
		return grp;
	}

	csch_attr_src_free(src);
	return NULL;
}

csch_cgrp_t *csch_loclib_get_root(csch_sheet_t *sheet, csch_lib_master_t *master, csch_source_arg_t *src, int alloc, int *alloced)
{
	return csch_loclib_get_root_by_name(sheet, master->name, src, alloc, alloced);
}


int csch_loclib_get_roots(csch_lib_t **root_dir_out, csch_cgrp_t **root_grp_out, csch_lib_master_t *master, csch_sheet_t *sheet, csch_source_arg_t *src, int alloc, int *alloced)
{
	csch_lib_root_t *libroot;
	csch_lib_t *root_dir;
	csch_cgrp_t *root_grp;


	*root_dir_out = NULL;
	*root_grp_out = NULL;
	if (alloc)
		*alloced = 0;

	if (master->uid >= sheet->local_libs.used) {
		rnd_message(RND_MSG_ERROR, "%s: master out of bounds #1\nPlease report this bug!\n", master->name);
		csch_attr_src_free(src);
		return -1;
	}

	libroot = sheet->local_libs.array[master->uid];
	if (libroot->roots.used < 1) {
		rnd_message(RND_MSG_ERROR, "%s: master out of bounds #2\nPlease report this bug!\n", master->name);
		csch_attr_src_free(src);
		return -1;
	}

	root_dir = libroot->roots.array[0];

	root_grp = csch_loclib_get_root(sheet, master, src, alloc, alloced);
	if (root_grp == NULL) {
		if (alloc)
			rnd_message(RND_MSG_ERROR, "%s: failed to create local devmap lib\nPlease report this bug!\n", master->name);
		return -1;
	}

	*root_dir_out = root_dir;
	*root_grp_out = root_grp;

	return 0;
}

long csch_loclib_reload_all(csch_sheet_t *sheet, csch_lib_root_t *libroot)
{
	long n, i, cnt = 0;

	for(n = 0; n < libroot->roots.used; n++) {
		csch_lib_t *root = libroot->roots.array[n];
		if (strcmp(root->name, "<local>") == 0) {
			for(i = root->children.used-1; i >= 0; i--) {
				csch_lib_t *l = root->children.array[i];
				if ((l != NULL) && (l->backend != NULL) && (l->backend->loc_refresh_from_ext != NULL)) {
					if (l->backend->loc_refresh_from_ext(sheet, l) == 0)
						cnt++;
				}
			}
			break;
		}
	}

	return cnt;
}

