// 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. 

// Copyright 2003 Liam Girdwood  

#include "deep_object.hh"
#include <libgnomecanvasmm/ellipse.h>

namespace Castor
{
	
DeepObject::DeepObject ()
{
	m_ra = 0;
	m_dec= 0;
	m_mag = 100;
	m_is_dec_negative = false;
}

DeepObject::~DeepObject()
{
}

/*! \fn bool DeepObject::check_element (std::string& name);
* \param name Name of the element type
* \return True, if the element type is known
*
* Is the element type known to the object.
*
* Elements known to this class are
* <ul>
* <li><b>  RA</b>		<i>Right Ascension (double)</i></li> 
* <li><b>  DEC</b>		<i>Declination (double)</i></li>
* <li><b>  RAh</b>		<i>Right Ascension hours (int)</i></li>
* <li><b>  RAm</b>		<i>Right Ascension minutes (int)</i></li>
* <li><b>  RAs</b>		<i>Right Ascension seconds (double)</i></li>
* <li><b>  DE-</b>		<i>Declination Sign (string)</i></li>
* <li><b>  DEd</b>		<i>Declination degrees (int)</i></li>
* <li><b>  DEm</b>		<i>Declination minutes (int)</i></li>
* <li><b>  DEs</b>		<i>Declination seconds (double)</i></li>
* <li><b>  Vmag</b>		<i>Visual Magnitude (double)</i></li>
* </ul>
*/
bool DeepObject::check_element (std::string& name)
{
	if (name == "RA")
		return true;
	if (name == "RAh")
		return true;
	if (name == "RAm")
		return true;
	if (name == "RAs")
		return true;
	if (name == "DEC")
		return true;
	if (name == "DEd")
		return true;
	if (name == "DEm")
		return true;
	if (name == "DEs")
		return true;
	if (name == "Vmag")
		return true;
	if (name == "DE-")
		return true;

	return AstroObject::check_element (name);
}

/*! \fn bool DeepObject::add_element (std::string& name, element_type type, std::string& value)
* \param name Name of the element type
* \param type Type of element INT, DOUBLE or STRING
* \param value Value of element
* \return True, if the element type is known
*
* Add the data element to this object. The element type is specified as either an 
* int, double or a string. If the element is unknown to this object, 
* it is passed down through to the next layer.
*
* Elements known to this class are
* <ul>
* <li><b>  RA</b>		<i>Right Ascension (double)</i></li> 
* <li><b>  DEC</b>		<i>Declination (double)</i></li>
* <li><b>  RAh</b>		<i>Right Ascension hours (int)</i></li>
* <li><b>  RAm</b>		<i>Right Ascension minutes (int)</i></li>
* <li><b>  RAs</b>		<i>Right Ascension seconds (double)</i></li>
* <li><b>  DE-</b>		<i>Declination Sign (string)</i></li>
* <li><b>  DEd</b>		<i>Declination degrees (int)</i></li>
* <li><b>  DEm</b>		<i>Declination minutes (int)</i></li>
* <li><b>  DEs</b>		<i>Declination seconds (double)</i></li>
* <li><b>  Vmag</b>		<i>Visual Magnitude (double)</i></li>
* </ul>
*/

bool DeepObject::add_element (std::string& name, element_type type,
									std::string& value)
{
	switch (type) {
		case DOUBLE: {
			double val = strtod (value.c_str(), 0);
			if (name == "RA") {
				m_ra = val;
				return true;
			}
			if (name == "DEC") {
				m_dec = val;
				return true;
			}
			if (name == "RAs") {
				m_ra += val * (15.0 / 60.0 / 60.0);
				return true;
			}
			if (name == "DEs") {
				if (m_is_dec_negative)
					m_dec -= val * (1.0 / 60.0 / 60.0);
				else
					m_dec += val * (1.0 / 60.0 / 60.0);
				return true;
			}
			if (name == "Vmag") {
				m_mag = val;
				return true;
			}
		}
		break;
		case INT: {
			int val = strtol (value.c_str(), 0, 10);
			if (name == "RAh") {
				m_ra += (double)val * 15.0;
				return true;
			}
			if (name == "RAm") {
				m_ra += (double)val * (15.0 / 60.0);
				return true;
			}
			if (name == "DEd") {
				if (m_is_dec_negative)
					m_dec -= (double)val;
				else
					m_dec += (double)val;
				return true;
			}
			if (name == "DEm") {
				if (m_is_dec_negative)
					m_dec -= (double)val * (1.0 / 60.0);
				else
					m_dec += (double)val * (1.0 / 60.0);
				return true;
			}
		}
		break;
		case STRING: {
			if (name == "DE-") {
				if (value == "-")
					m_is_dec_negative = true;
				return true;
			}
		break;
		}
	}
	
	// no match, then try lower layers
	return AstroObject::add_element (name, type, value);
}

/* \fn double DeepObject::get_distance_ly ();
* \return Object Distance in light years
*
* Get the object distance (ly)
*/
double DeepObject::get_distance_ly ()
{
	return m_distance_ly;
}

/* \fn double DeepObject::get_distance_ps ();
* \return Object distance in parsecs
*
* Get the object distance (parsecs)
*/
double DeepObject::get_distance_ps ()
{
	return m_distance_ly * 1.0; //liam need constant
}

/*! \fn void DeepObject::get_equ_posn (double JD, ln_equ_posn* posn);
* \param JD Julian day
* \param posn Pointer to a struct ln_equ_posn
*
* Get object Right Ascension and Declination for the given JD
*/
void DeepObject::get_equ_posn (double JD, double& ra, double& dec)
{
	ra = m_ra;
	dec = m_dec;
}

/*! \fn void DeepObject::get_hrz_posn (double JD, ln_lnlat_posn* observer, ln_hrz_posn* posn);
* \param JD Julian day
* \param observer Pointer to observers longitude and latitude
* \param posn Pointer to a struct ln_hrz_posn
*
* Get object Altitude and Azimuth for the given JD
*/
void DeepObject::get_hrz_posn (double JD, ln_lnlat_posn* observer, ln_hrz_posn* posn)
{
}

/*! \fn void  DeepObject::get_rst_time (double JD, ln_lnlat_posn* observer, ln_rst_time* time)
* \param JD Julian day
* \param observer Pointer to observers longitude and latitude.
* \param time Pointer to a struct ln_rst_time
*
* Get object Rise, Set and Transit time for the given JD
*/
void DeepObject::get_rst_time (double JD, ln_lnlat_posn* observer, ln_rst_time* time)
{
}

int DeepObject::save (std::ofstream* file)
{
	save_item (file, m_ra);
	save_item (file, m_dec);
	save_item (file, m_mag);
	
	AstroObject::save(file);
}

int DeepObject::load (std::ifstream* file)
{
	load_item (file, m_ra);
	load_item (file, m_dec);
	load_item (file, m_mag);

	AstroObject::load(file);
}

double DeepObject::get_mag (double JD)
{
	return m_mag;
}

int DeepObject::init ()
{
	return AstroObject::init();
}

/*! \fn virtual get_info (std::list<Glib::ustring> name,  std::list<Glib::ustring> value);
* \param name List of parameter names.
* \param value List of parameter values.
*/
void DeepObject::get_info (std::list<Glib::ustring>& name,  std::list<Glib::ustring>& value)
{
	char temp[32];
	struct ln_hms hms;
	struct ln_dms dms;
	
	ln_deg_to_dms (m_dec, &dms);
	ln_deg_to_hms (m_ra, &hms);
	
	name.push_front(Glib::ustring("Dist(ly)"));
	sprintf(temp, "%4.2f", m_distance_ly);
	value.push_front(Glib::ustring(temp)); 
	
	name.push_front(Glib::ustring("Vmag"));
	sprintf(temp, "%4.2f", m_mag);
	value.push_front(Glib::ustring(temp)); 
	
	name.push_front(Glib::ustring("DEC"));
	sprintf(temp, "%d:%d:%4.2f", dms.degrees, dms.minutes, dms.seconds);
	value.push_front(Glib::ustring(temp));
	
	name.push_front(Glib::ustring("RA"));
	sprintf(temp, "%d:%d:%4.2f", hms.hours, hms.minutes, hms.seconds);
	value.push_front(Glib::ustring(temp)); 
	
	AstroObject::get_info (value);
}

void DeepObject::render(double x, double y, double mag_max, Gnome::Canvas::Group& group, bool bright, double ppd)
{
	// draw object on canvas
	double size = (mag_max + 1) - m_mag;
	double shadow = 1.1 * size;
	Gnome::Canvas::Ellipse *ellipse_back, *ellipse;
	
	if (!bright) {
		// draw the background shadow object
		ellipse_back = Gtk::manage (new Gnome::Canvas::Ellipse(group, x - shadow, y - shadow, x + shadow, y + shadow));
		*ellipse_back << Gnome::Canvas::Properties::fill_color("black");
		ellipse_back->show();
	}
	
	// draw real colour object
	ellipse = Gtk::manage (new Gnome::Canvas::Ellipse(group, x - size, y - size, x + size, y + size));
	ellipse->set_data (Glib::Quark("object"),(gpointer)this);
	*ellipse << Gnome::Canvas::Properties::fill_color(Gdk::Color("white"));
	ellipse->show();
}

}


syntax highlighted by Code2HTML, v. 0.9.1