/*
 *                            COPYRIGHT
 *
 *  camv-rnd - electronics-related CAM viewer
 *  Copyright (C) 2019 Tibor 'Igor2' Palinkas
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 31 Milk Street, # 960789 Boston, MA 02196 USA.
 *
 *  Contact:
 *    Project page: http://repo.hu/projects/camv-rnd
 *    lead developer: http://repo.hu/projects/camv-rnd/contact.html
 *    mailing list: pcb-rnd (at) list.repo.hu (send "subscribe")
 */

#include <librnd/config.h>

#include "obj_grp.h"
#include "obj_any.h"

static void camv_grp_free_fields(camv_any_obj_t *obj)
{
	rnd_cardinal_t n;
	camv_any_obj_t *gobj;
	for(n = 0, gobj = obj->grp.objs; n < obj->grp.len; n++,gobj++)
		gobj->proto.calls->free_fields(gobj);
	free(obj->grp.objs);
	obj->grp.objs = NULL;
	obj->grp.len = 0;
}

static void camv_grp_draw(camv_any_obj_t *obj, rnd_hid_gc_t gc, rnd_xform_mx_t *mx)
{
	rnd_cardinal_t n;
	camv_any_obj_t *gobj;
	for(n = 0, gobj = obj->grp.objs; n < obj->grp.len; n++,gobj++)
		gobj->proto.calls->draw(gobj, gc, mx);
}

static void camv_grp_bbox(camv_any_obj_t *obj)
{
	rnd_cardinal_t n;
	camv_any_obj_t *gobj;

	gobj = obj->grp.objs;
	obj->grp.bbox = *camv_obj_bbox(gobj);
	for(n = 1, gobj++; n < obj->grp.len; n++,gobj++)
		camv_rtree_box_bump(&obj->grp.bbox, camv_obj_bbox(gobj));
	obj->arc.bbox_valid = 1;
}

static void camv_grp_copy(camv_any_obj_t *dst, const camv_any_obj_t *src)
{
	rnd_cardinal_t n;
	camv_any_obj_t *sobj, *dobj;

	memcpy(&dst->proto, &src->proto, sizeof(src->proto));
	dst->grp.len = src->grp.len;
	dst->grp.objs = malloc(sizeof(camv_any_obj_t) * src->grp.len);
	for(n = 0, sobj = src->grp.objs, dobj = dst->grp.objs; n < src->grp.len; n++,sobj++,dobj++)
		sobj->proto.calls->copy(dobj, sobj);
}

static void camv_grp_move(camv_any_obj_t *g, rnd_coord_t dx, rnd_coord_t dy)
{
	rnd_cardinal_t n;
	camv_any_obj_t *o;

	for(n = 0, o = g->grp.objs; n < g->grp.len; n++,o++)
		o->proto.calls->move(o, dx, dy);

	if (g->grp.bbox_valid) {
		g->grp.bbox.x1 += dx; g->grp.bbox.y1 += dy;
		g->grp.bbox.x2 += dx; g->grp.bbox.y2 += dy;
	}
}

static camv_any_obj_t *camv_grp_alloc(void) { return (camv_any_obj_t *)camv_grp_new(); }

static int camv_grp_isc_box(const camv_any_obj_t *obj, const camv_rtree_box_t *box)
{
	rnd_cardinal_t n;
	camv_any_obj_t *gobj;

	for(n = 0, gobj = obj->grp.objs; n < obj->grp.len; n++,gobj++)
		if (gobj->proto.calls->isc_box(gobj, box))
			return 1;


	return 0;
}


static const camv_objcalls_t camv_grp_calls = {
	camv_grp_alloc,
	camv_grp_free_fields,
	camv_grp_draw,
	camv_grp_bbox,
	camv_grp_copy,
	camv_grp_move,
	camv_grp_isc_box
};

void camv_grp_init(camv_grp_t *grp)
{
	memset(grp, 0, sizeof(camv_grp_t));
	grp->type = CAMV_OBJ_GRP;
	grp->calls = &camv_grp_calls;
}

camv_grp_t *camv_grp_new(void)
{
	camv_grp_t *res = malloc(sizeof(camv_grp_t));
	camv_grp_init(res);
	return res;
}

