/*
 *                            COPYRIGHT
 *
 *  pcb-rnd, interactive printed circuit board design
 *  Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *  Contact:
 *    Project page: http://repo.hu/projects/pcb-rnd
 *    lead developer: http://repo.hu/projects/pcb-rnd/contact.html
 *    mailing list: pcb-rnd (at) list.repo.hu (send "subscribe")
 */

#ifndef PCB_OBJ_SUBC_PARENT_H
#define PCB_OBJ_SUBC_PARENT_H

#include "data.h"
#include "data_parent.h"
#include "layer.h"

/* Returns the subc a global (on-data) object is part of (or NULL if not part of any subc) */
RND_INLINE pcb_subc_t *pcb_gobj_parent_subc(pcb_parenttype_t pt, const pcb_parent_t *p)
{
	if (pt != PCB_PARENT_DATA)
		return NULL;

	if (p->data == NULL)
		return NULL;
	
	if (p->data->parent_type == PCB_PARENT_SUBC)
		return p->data->parent.subc;
	return NULL;
}

/* Returns the subc a layer object is part of (or NULL if not part of any subc) */
RND_INLINE pcb_subc_t *pcb_lobj_parent_subc(pcb_parenttype_t pt, const pcb_parent_t *p)
{
	if (pt != PCB_PARENT_LAYER)
		return NULL;

	if (p->layer == NULL)
		return NULL;
	
	if (p->layer->parent.data == NULL)
		return NULL;

	if (p->layer->parent.data->parent_type == PCB_PARENT_SUBC)
		return p->layer->parent.data->parent.subc;
	return NULL;
}

/* Returns the subc an object is part of (or NULL if not part of any subc) */
RND_INLINE pcb_subc_t *pcb_obj_parent_subc(const pcb_any_obj_t *obj)
{
	switch(obj->type) {
		case PCB_OBJ_PSTK:
		case PCB_OBJ_SUBC:
			return pcb_gobj_parent_subc(obj->parent_type, &obj->parent);

		case PCB_OBJ_LINE:
		case PCB_OBJ_POLY:
		case PCB_OBJ_TEXT:
		case PCB_OBJ_ARC:
		case PCB_OBJ_GFX:
			return pcb_lobj_parent_subc(obj->parent_type, &obj->parent);

		default:
			/* anything else: virtual */
			return 0;
	}
	return 0;
}

RND_INLINE rnd_bool_t pcb_obj_is_under(pcb_any_obj_t *obj, pcb_data_t *data)
{
	for(;;) {
		switch(obj->parent_type) {
			case PCB_PARENT_INVALID: return rnd_false;
			case PCB_PARENT_BOARD:   return rnd_false;
			case PCB_PARENT_UI:      return rnd_false; /* shouldn't happen */
			case PCB_PARENT_LAYER:   if (obj->parent.layer->parent.data == data) return rnd_true; break;
			case PCB_PARENT_SUBC:    if (obj->parent.subc->data == data) return rnd_true; break;
			case PCB_PARENT_DATA:    if (obj->parent.data == data) return rnd_true; break;
			case PCB_PARENT_NET:     if (obj->parent.data == data) return rnd_true; break;
		}
		obj = (pcb_any_obj_t *)pcb_obj_parent_subc(obj);
		if (obj == NULL)
			return rnd_false;
	}
}


#endif
