/*****************************************************
**
**   EphemExpert   ---   writeLunar
**
******************************************************/
void EphemExpert::writeLunar( Writer *writer )
{
	if ( ! clunar ) calcLunar();
	Lang lang;
	wxString s, thetime;
	list<LunarEvent>::iterator iter;
	LunarEvent *e;
	TzUtil tzu;

	writeHeaderInfo( writer );
	Table table( 7, lunarEvents.size()+1 );
	table.setHeader( 0, _( "Day" ));
	table.setHeader( 1, _( "Time" ));
	table.setHeader( 2, _( "Sun" ));
	table.setHeader( 3, _( "Moon" ));
	table.setHeader( 4, _( "Angle" ));
	table.setHeader( 5, _( "Tithi" ));
	table.setHeader( 6, _( "Western" ));

	int line = 1;
	for ( iter = lunarEvents.begin(); iter != lunarEvents.end(); iter++ )
	{
		e = (LunarEvent*)(&(*iter));
		TzFormattedDate fd = tzu.getDateFormatted( e->jd, isLocaltime );
		thetime = fd.timeFormatted;
		//if ( dstchange ) thetime << wxT( " " ) << fd.timezoneFormatted;

		s.Printf( wxT( "%02d %s" ), fd.dayOfMonth, fd.weekDay.c_str());
		if ( testDayIndexForCurrent( fd.dayOfMonth )) table.setHeaderEntry( 0, line, s );
		else	table.setEntry( 0, line, s );

		table.setEntry( 1, line, thetime );
		table.setEntry( 2, line, writer->getPosFormatted( e->slen, false ) );
		table.setEntry( 3, line, writer->getPosFormatted( e->mlen, false ) );

		int angle = (int)( red_deg( e->mlen - e->slen ) + .00001 );
		if ( angle >= 360 ) angle -= 360;
		s.Printf( wxT( "%d" ), angle );
		table.setEntry( 4, line, s );

		if ( ! ( angle % 12 ))
		{
			table.setEntry( 5, line, lang.getTithiName( angle / 12 ) );
		}
		if ( angle == 0 ) table.setEntry( 6, line, _( "New Moon" ));
		else if ( angle == 180 ) table.setEntry( 6, line, _( "Full Moon" ));
		else if ( angle == 60 || angle == 300 ) table.setEntry( 6, line, _( "Sextile" ));
		else if ( angle == 90 ) table.setEntry( 6, line, _( "Half Moon (Waxing)" ));
		else if ( angle == 120 || angle == 240 ) table.setEntry( 6, line, _( "Trine" ));
		else if ( angle == 270 ) table.setEntry( 6, line, _( "Half Moon (Waning)" ));

		// Semi squares
		else if (( angle == 45 || angle == 135 || angle == 225 || angle == 315 ))
			table.setEntry( 6, line, _( "Semi Square" ));
		line++;
	}
	writer->writeTable( table );
}
/*****************************************************
**
**   EphemExpert   ---   writeDetails
**
******************************************************/
void EphemExpert::writeDetails( Writer *writer )
{
	int i;
	wxString s, tz_str, thetime;
	Lang lang;
	Formatter *formatter = Formatter::get();
	TzUtil tzu;

	if ( ! cdetails ) calcDetails();

	s.Printf( wxT ( "%s %d" ), (const wxChar*)lang.getMonthName( month-1 ), year );
	writer->writeHeader1( s );

	int line = 1;
	int nb_leaps = 0;
	for ( i = 0; i < nb_days; i++ )
	{
		if ( i > 0 && weekday[i] == 0 ) nb_leaps++;
	}
	Table table( 5, nb_days+1+nb_leaps );
	table.setHeader( 0, _( "Day" ));
	table.setHeader( 1, _( "Sidereal Time" ));
	table.setHeader( 2, _( "Sunrise" ));
	table.setHeader( 3, _( "Sunset" ));
	table.setHeader( 4, _( "Tithi (Sunrise)" ));

	line = 1;
	for ( i = 0; i < nb_days; i++ )
	{
		// blank line on weekend
		if ( i > 0 && weekday[i] == 0 )
		{
			for ( int j = 0; j < 5; j++ ) table.setHeaderEntry( j, line, wxEmptyString );
			line++;
		}

		s.Printf( wxT( "%02d %s" ), i+1, (const wxChar*)lang.getWeekdayName( weekday[i] ).Left(2) );
		if ( testDayIndexForCurrent( i+1 )) table.setHeaderEntry( 0, line, s );
		else	table.setEntry( 0, line, s );

		table.setEntry( 1, line, formatter->getTimeFormatted( st[i] ) );

		TzFormattedDate fd = tzu.getDateFormatted( sunrise[i], isLocaltime );
		thetime = fd.timeFormatted;
		//if ( dstchange ) thetime << wxT( " " ) << fd.timezoneFormatted;
		table.setEntry( 2, line, thetime );

		fd = tzu.getDateFormatted( sunset[i], isLocaltime );
		table.setEntry( 3, line, fd.timeFormatted );

		table.setEntry( 4, line, lang.getTithiName( tithi[i] ));
		line++;
	}
	writer->writeTable( table );
}
/*****************************************************
**
**   GenericTableWriter   ---   writeCustomDataEntry
**
******************************************************/
void GenericTableWriter::writeCustomDataEntry( const uint &col, const uint &row, const TAB_CELL_TYPE &type )
{
	assert( table->getNbCols() > col );
	assert( table->getNbRows() > row );
	Formatter *f = Formatter::get();
	DateTimeFormatter *df = DateTimeFormatter::get();
	Lang lang;
	wxString s;
	
	switch( type )
	{
		case TAB_CELL_NAME:
			table->setEntry( col, row,  _( "Name" ));
			table->setEntry( col + 1, row, h->getHName() );
		break;
		case TAB_CELL_FULL_DATE:
		{
			table->setEntry( col, row,  _( "Date" ));
			Location *loc = h->getDataSet()->getLocation();
			table->setEntry( col + 1, row, df->formatDateString( h->getJD(), loc->getTimeZone() + loc->getDST()));
		}
		break;
		case TAB_CELL_LOCAL_TIME:
		{
			table->setEntry( col, row,  _( "Local Time" ));
			Location *loc = h->getDataSet()->getLocation();
			table->setEntry( col + 1, row, f->getTimeFormatted( a_red( getTimeFromJD( h->getDataSet()->getDate()->getJD()) + loc->getTimeZone() + loc->getDST(), 24 )));
		}
		break;
		case TAB_CELL_LOCATION_NAME:
			table->setEntry( col, row,  _( "Location" ));
			table->setEntry( col + 1, row, h->getDataSet()->getLocation()->getLocName() );
		break;
		case TAB_CELL_LOCATION_LONGITUDE:
		{
			table->setEntry( col, row,  _( "Longitude" ));
			Location *loc = h->getDataSet()->getLocation();
			table->setEntry( col + 1, row, f->getLongitudeFormatted( loc->getLongitude()));
		}
		break;
		case TAB_CELL_LOCATION_LATITUDE:
		{
			table->setEntry( col, row,  _( "Latitude" ));
			Location *loc = h->getDataSet()->getLocation();
			table->setEntry( col + 1, row, f->getLatitudeFormatted( loc->getLatitude()));
		}
		break;
		case TAB_CELL_TZ_NAME:
		{
			table->setEntry( col, row,  _( "Time Zone" ));
			Location *loc = h->getDataSet()->getLocation();
			const double tz = loc->getTimeZone();
			table->setEntry( col + 1, row, wxString::Format( wxT( "%s %c%.1f" ), _( "UT" ), ( tz >= 0 ? '+' : ' ' ), tz ));
		}
		break;
		case TAB_CELL_DST:
		{
			table->setEntry( col, row,  _( "Daylight Saving" ));
			Location *loc = h->getDataSet()->getLocation();
			table->setEntry( col + 1, row, wxString::Format( wxT( "%.1f" ), loc->getDST()));
		}
		break;
		case TAB_CELL_UNIVERSAL_TIME:
			table->setEntry( col, row,  _( "Universal Time" ));
			table->setEntry( col + 1, row, f->getTimeFormatted( getTimeFromJD( h->getJD() )));
		break;
		case TAB_CELL_SIDEREAL_TIME:
			table->setEntry( col, row,  _( "Sidereal Time" ));
			table->setEntry( col + 1, row, f->getTimeFormatted( h->getSiderealTime()));
		break;
		case TAB_CELL_JULIAN_DATE:
			table->setEntry( col, row,  _( "Julian Date" ));
			table->setEntry( col + 1, row, wxString::Format( wxT( "%8.5f" ), h->getJD()));
		break;
		case TAB_CELL_SUNRISE:
		{
			table->setEntry( col, row,  _( "Sunrise" ));
			Location *loc = h->getLocation();
			if ( h->getSunrise() != 0 )
			{
				s = f->getTimeFormatted( getTimeFromJD( h->getSunrise() + ( loc->getTimeZone() + loc->getDST()) / 24.0 ));
			}
			else s = _( "n.a." );
			table->setEntry( col + 1, row, s );
		}
		break;
		case TAB_CELL_SUNSET:
		{
			table->setEntry( col, row,  _( "Sunset" ));
			Location *loc = h->getLocation();
			if ( h->getSunset() != 0 )
			{
				s = f->getTimeFormatted( getTimeFromJD( h->getSunset() + ( loc->getTimeZone() + loc->getDST()) / 24.0 ));
			}
			else s = _( "n.a." );
			table->setEntry( col + 1, row, s );
		}
		break;
		case TAB_CELL_VEDIC_AYANAMSA:
			table->setEntry( col, row,  _( "Vedic Ayanamsa" ));
			table->setEntry( col + 1, row, f->getAyanamsaNameAndValue( h->getAyanamsaType( true ), h->getAyanamsa( true )));
		break;
		case TAB_CELL_WESTERN_AYANAMSA:
			table->setEntry( col, row,  _( "Western Ayanamsa" ));
			table->setEntry( col + 1, row, f->getAyanamsaNameAndValue( h->getAyanamsaType( false ), h->getAyanamsa( false )));
		break;
		case TAB_CELL_VARNA:
			table->setEntry( col, row,  _( "Varna" ));
			table->setEntry( col + 1, row, lang.getVarnaName( getVarna( h->getVedicLongitude( OMOON ))));
		break;
		case TAB_CELL_GANA:
			table->setEntry( col, row,  _( "Gana" ));
			table->setEntry( col + 1, row, lang.getGanaName( NakshatraExpert().getGana( h->getVedicLongitude( OMOON ))));
		break;
		case TAB_CELL_YONI:
		{
			Yoni yoni = NakshatraExpert().getYoni( h->getVedicLongitude( OMOON ));
			table->setEntry( col, row,  _( "Yoni" ));
			table->setEntry( col + 1, row, yoni.name );
		}
		break;
		case TAB_CELL_NADI:
			table->setEntry( col, row,  _( "Nadi" ));
			table->setEntry( col + 1, row, lang.getNadiName( NakshatraExpert().getNadi( h->getVedicLongitude( OMOON ))));
		break;
		case TAB_CELL_RAJJU:
		{
			Rajju rajju = NakshatraExpert().getRajju( getNakshatra27( h->getVedicLongitude( OMOON )));
			table->setEntry( col, row,  _( "Rajju" ));
			table->setEntry( col + 1, row, lang.getRajjuName( rajju.aroha, rajju.type ));
		}
		break;
		case TAB_CELL_INCFLUENCE_TIME:
		{
			DasaExpert *expert = DasaExpertFactory().getDasaExpert( D_VIMSOTTARI, h );
			table->setEntry( col, row,  _( "Influence" ));
			table->setEntry( col + 1, row, expert->getDasaLordNameF( expert->getBirthMahaDasaLord(), TF_LONG ));
		}
		break;

		case TAB_CELL_LUNAR_TITHI:
		{
			double angle = red_deg( h->getVedicLongitude( OMOON ) - h->getVedicLongitude( OSUN ));
			table->setEntry( col, row,  _( "Lunar Tithi" ));
			table->setEntry( col + 1, row,  lang.getTithiName( angle / 12 ));
		}
		break;
		case TAB_CELL_WEEKDAY:
			table->setEntry( col, row,  _( "Weekday" ));
			table->setEntry( col + 1, row,  lang.getWeekdayName( h->getDataSet()->getWeekDay() ));
		break;

		case TAB_CELL_HORA_LORD:
		case TAB_CELL_DINA_LORD:
		case TAB_CELL_MASA_LORD:
		case TAB_CELL_VARSHA_LORD:
			writeHoraEntry( col, row, type );
		break;
		default:
			table->setEntry( col, row,  wxString::Format( wxT( "Error, wrong custom data entry id %d" ), (int)type ));
		break;
	};
}