/**************************************************************

mv_apertures.cpp (C-Munipack project)
List of apertures
Copyright (C) 2012 David Motl, dmotl@volny.cz

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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

**************************************************************/
#include <stdlib.h>
#include <stdio.h>

#include "mv_apertures.h"

#define ALLOC_BY 12

//-------------------------   TABLE OF APERTURES   ------------------------

// Default constructor
CApertures::CApertures():m_Count(0), m_Capacity(0), m_List(NULL)
{
}

// Copy constructor
CApertures::CApertures(const CApertures &orig):m_Count(0), m_Capacity(0), 
	m_List(NULL)
{
	int i, count;

	count = orig.Count();
	if (count>0) {
		m_Capacity = count;
		m_List = (CAperture**)malloc(m_Capacity*sizeof(CAperture*));
		for (i=0; i<count; i++) {
			const CAperture *ap = orig.Get(i);
			m_List[i] = (ap!=NULL ? new CAperture(*ap) : NULL);
		}
		m_Count = count;
	}
}

// Destructor
CApertures::~CApertures()
{
	for (int i=0; i<m_Count; i++)
		delete m_List[i];
	free(m_List);
}

// assignment operator
CApertures &CApertures::operator=(const CApertures &orig)
{
	int i, count;

	if (&orig!=this) {
		Clear();
		count = orig.Count();
		if (count>0) {
			m_Capacity = count;
			m_List = (CAperture**)malloc(m_Capacity*sizeof(CAperture*));
			for (i=0; i<count; i++) {
				const CAperture *ap = orig.Get(i);
				m_List[i] = (ap!=NULL ? new CAperture(*ap) : NULL);
			}
			m_Count = count;
		}
	}
	return *this;
}

// Clear the table
void CApertures::Clear(void)
{
	for (int i=0; i<m_Count; i++)
		delete m_List[i];
	free(m_List);
	m_List = NULL;
	m_Count = m_Capacity = 0;
}

// Add an aperture, if the aperture with the same id is 
// in the table, it changes its parameters
void CApertures::Add(const CAperture &item)
{
	int index = Find(item.Id());
	if (index<0) {
		if (m_Count>=m_Capacity) {
			m_Capacity += ALLOC_BY;
			CAperture **old_list = m_List;
			m_List = (CAperture**)realloc(m_List, m_Capacity*sizeof(CAperture*));
			if (!m_List) 
				free(old_list);
		}
		if (m_List)
			m_List[m_Count++] = new CAperture(item);
	} else 
		*m_List[index] = item;
}

// Find aperture by id 
int CApertures::Find(int id) const
{
	int i;

	for (i=0; i<m_Count; i++) {
		if (m_List[i]->Id() == id)
			return i;
	}
	return -1;
}

// Return index of smallest aperture
int CApertures::FindSmallest(void) const
{
	int i, imin = -1;
	double qmin = 1e99;

	for (i=0; i<m_Count; i++) {
		if (m_List[i]->Radius() < qmin) {
			imin = i;
			qmin = m_List[i]->Radius();
		}
	}
	return imin;
}

const CAperture *CApertures::Get(int index) const
{
	if (index>=0 && index<m_Count)
		return m_List[index];
	return NULL;
}

// Get aperture by index
int CApertures::GetId(int index) const
{
	if (index>=0 && index<m_Count)
		return m_List[index]->Id();
	return -1;
}

// Get aperture by index
double CApertures::GetRadius(int index) const
{
	if (index>=0 && index<m_Count)
		return m_List[index]->Radius();
	return 0.0;
}
