#ifndef _EVENT_H_
#define _EVENT_H_
///
///   @file	Event.h
///
///   @brief Header file for the Event Class, the main data container
///
///   @class Event
///   @brief Event is the primary data container for the SOFIE level1 processing
///
///
///
///   @author John Burton <j.c.burton@gats-inc.com>
/// 
///   @date  Thu Apr 20 09:17:10 2006
///
///   @copyright
///   (&copy;) Copyright 2006 by GATS, Inc.,
///   11864 Canon Blvd, Suite 101, Newport News VA 23606
///
///   All Rights Reserved. No part of this software or publication may be
///   reproduced, stored in a retrieval system, or transmitted, in any form
///   or by any means, electronic, mechanical, photocopying, recording, or
///   otherwise without the prior written permission of GATS, Inc.
///
///

//
//-----------------------------------------------------------------------
// Include Files:
//-----------------------------------------------------------------------
//
#include "EventVar.h"
#include "EventVarVect.h"
//#include "GATS_Exception.h"
//#include "SOFIE_Exception.h"
#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <stdexcept>

//
//-----------------------------------------------------------------------
// Defines, Macros and Type Definitions:
//-----------------------------------------------------------------------
//
 
enum DataType {
  NOVAR   = 0,
  INTEGER = 1,
  FLOAT   = 2,
  DOUBLE  = 3
};

//
//class EventNameException : public GATS_Exception
//{
//public:
//  EventNameException(std::string msg, const char *filename,
//		     const unsigned int linenumber) : GATS_Exception(msg.c_str(),filename,linenumber) {}
//};


class Event{
public:
  ///
  /// Default Event constructor
  ///
  Event();

  ///
  /// Event constructor setting property listed in parameters
  /// @param en - Event Number
  ///
  Event(int en);

  ///
  /// Event constructor setting property listed in parameters
  /// @param en - Event Number from start of mission
  /// @param on - Orbit Number from start of mission
  ///
  Event(int en, int on);

  ///
  /// Event constructor setting property listed in parameters
  /// @param en - Event Number from start of mission
  /// @param on - Orbit Number from start of mission
  /// @param flag - Sunrise / Sunset flag
  ///
  Event(int en, int on, char flag);

  ///
  /// Event constructor setting property listed in parameters
  /// @param en - Event Number from start of mission
  /// @param on - Orbit Number from start of mission
  /// @param flag - Sunrise / Sunset flag
  /// @param start - Event Start Time
  ///
  Event(int en, int on, char flag, int start);

  ///
  /// Event constructor setting property listed in parameters
  /// @param en - Event Number from start of mission
  /// @param on - Orbit Number from start of mission
  /// @param flag - Sunrise / Sunset flag
  /// @param start - Event Start Time
  /// @param stop - Event Stop Time
  ///
  Event(int en, int on, char flag, int start, int stop);

  ///
  /// Event constructor setting property listed in parameters
  /// @param en - Event Number from start of mission
  /// @param on - Orbit Number from start of mission
  /// @param flag - Sunrise / Sunset flag
  /// @param start - Event Start Time
  /// @param stop - Event Stop Time
  /// @param lat - Event Latitude at 83km
  ///
  Event(int en, int on, char flag, int start, int stop, float lat);

  ///
  /// Event constructor setting property listed in parameters
  /// @param en - Event Number from start of mission
  /// @param on - Orbit Number from start of mission
  /// @param flag - Sunrise / Sunset flag
  /// @param start - Event Start Time
  /// @param stop - Event Stop Time
  /// @param lat - Event Latitude at 83km
  /// @param lon - Event Longitude at 83km
  ///
  Event(int en, int on, char flag, int start, int stop, float lat, float lon);

  ///
  /// Default destructor
  ///
  ~Event();

  ///
  /// Clear the EventVar maps and reset the other properties back to default values.
  ///
  void clear();

  ///
  /// Open the EventLog
  ///
  void openEventLog();

  ///
  /// Close the EventLog
  ///
  void closeEventLog();

  ///
  /// Open the EventLog with writing to file \c filename enabled
  /// @param filename - name of file to be opened in append mode
  ///
  void openEventLog(std::string filename);

  ///
  /// Open the EventLog with writing to file \c filename enabled
  /// @param filename - name of file to be opened in append mode
  ///
  void openEventLog(char *filename);

  ///
  /// Add the string \c entry to the EventLog
  /// @param entry - string to append to the log
  ///
  void addLogEntry(std::string entry);

  ///
  /// Enables prepending a date/time stamp to each log entry
  ///
  void enableLogTimeStamp();

  ///
  /// Disables the date/time stamp 
  ///
  void disableLogTimeStamp();

  ///
  /// Displays the contents of the EventLog
  ///
  void PrintLog();

  ///
  /// Determines if an EventVar with the name \c name already exists in the Event object
  /// @param name - name to lookup
  /// @return - 0 (NONE) if the EventVar \c name is not in the Event object
  /// @return - 1 (INT) if the EventVar \c name exists and is of type \c <int>
  /// @return - 2 (FLOAT) if the EventVar \c name exists and is of type \c <float>
  /// @return - 3 (DOUBLE) if the EventVar \c name exists and is of type \c <double>
  ///
  int EventVarExists(std::string name);

  ///
  /// Add a copy of an EventVar<int> to the Event object
  /// Throws an EventNameException if an EventVar by the same name exists
  /// @param EV - integer EventVar to be added to the Event object
  ///
  void addEventVar(EventVar<int> &EV);

  ///
  /// Add a copy of an EventVar<float> to the Event object
  /// Throws an EventNameException if an EventVar by the same name exists
  /// @param EV - float EventVar to be added to the Event object
  ///
  void addEventVar(EventVar<float> &EV);

  ///
  /// Add a copy of an EventVar<double> to the Event object
  /// Throws an EventNameException if an EventVar by the same name exists
  /// @param EV - double EventVar to be added to the Event object
  ///
  void addEventVar(EventVar<double> &EV);

  ///
  /// Add an EventVar<int> pointed to by \c EV to the Event object
  /// Throws an EventNameException if an EventVar by the same name exists
  /// @param EV - pointer to the integer EventVar to be added to the Event object
  ///
  void addEventVar(EventVar<int> *EV);

  ///
  /// Add an EventVar<float> pointed to by \c EV to the Event object
  /// Throws an EventNameException if an EventVar by the same name exists
  /// @param EV - pointer to the float EventVar to be added to the Event object
  ///
  void addEventVar(EventVar<float> *EV);

  ///
  /// Add an EventVar<double> pointed to by \c EV to the Event object
  /// Throws an EventNameException if an EventVar by the same name exists
  /// @param EV - pointer to the double EventVar to be added to the Event object
  ///
  void addEventVar(EventVar<double> *EV);

  ///
  /// Add an EventVarVect<int> to the Event object
  /// Throws an EventNameException if an EventVar by the same name exists
  /// @param EV - EventVarVect to be added to the Event object
  ///
  void addEventVar(EventVarVect<int> &EVV);

  ///
  /// Add an EventVarVect<float> to the Event object
  /// Throws an EventNameException if an EventVar by the same name exists
  /// @param EV - EventVarVect to be added to the Event object
  ///
  void addEventVar(EventVarVect<float> &EVV);

  ///
  /// Add an EventVarVect<double> to the Event object
  /// Throws an EventNameException if an EventVar by the same name exists
  /// @param EV - EventVarVect to be added to the Event object
  ///
  void addEventVar(EventVarVect<double> &EVV);

  ///
  /// Add an EventVarVect<int> to the Event object
  /// Throws an EventNameException if an EventVar by the same name exists
  /// @param EV - EventVarVect to be added to the Event object
  ///
  void addEventVar(EventVarVect<int> *EVV);

  ///
  /// Add an EventVarVect<float> to the Event object
  /// Throws an EventNameException if an EventVar by the same name exists
  /// @param EV - EventVarVect to be added to the Event object
  ///
  void addEventVar(EventVarVect<float> *EVV);

  ///
  /// Add an EventVarVect<double> to the Event object
  /// Throws an EventNameException if an EventVar by the same name exists
  /// @param EV - EventVarVect to be added to the Event object
  ///
  void addEventVar(EventVarVect<double> *EVV);

  ///
  /// Gets a copy of an EventVar<int> from the Event object
  /// Throws an EventNameException if the EventVar name is not found
  /// @param name - name of the EventVar to be retrieved
  /// @param EV - copy of the integer EventVar to be retrieved from the Event object
  ///
  void getEventVar(std::string name, EventVar<int> &EV);

  ///
  /// Gets a copy of an EventVar<int> from the Event object
  /// Throws an EventNameException if the EventVar name is not found
  /// @param name - name of the EventVar to be retrieved
  /// @param EV - copy of the integer EventVar to be retrieved from the Event object
  ///
  void getEventVar(std::string name, EventVar<float> &EV);

  ///
  /// Gets a copy of an EventVar<int> from the Event object
  /// Throws an EventNameException if the EventVar name is not found
  /// @param name - name of the EventVar to be retrieved
  /// @param EV - copy of the integer EventVar to be retrieved from the Event object
  ///
  void getEventVar(std::string name, EventVar<double> &EV);

  ///
  /// Gets an EventVarVect<int> from the Event object
  /// Throws an EventNameException if the EventVarVect name is not found
  /// Caution - the EventVarVect object contains pointers to the actual EventVar object(s),
  /// not just a copy of the EventVarobject(s)
  /// @param name - name of the EventVar to be retrieved
  /// @param EVV - copy of the integer EventVarVect to be retrieved from the Event object
  ///
  void getEventVar(std::string name, EventVarVect<int> &EVV);

  ///
  /// Gets an EventVarVect<int> from the Event object
  /// Throws an EventNameException if the EventVarVect name is not found
  /// Caution - the EventVarVect object contains pointers to the actual EventVar object(s),
  /// not just a copy of the EventVarobject(s)
  /// @param name - name of the EventVar to be retrieved
  /// @param EVV - copy of the integer EventVarVect to be retrieved from the Event object
  ///
  void getEventVar(std::string name, EventVarVect<float> &EVV);

  ///
  /// Gets an EventVarVect<int> from the Event object
  /// Throws an EventNameException if the EventVarVect name is not found
  /// Caution - the EventVarVect object contains pointers to the actual EventVar object(s),
  /// not just a copy of the EventVarobject(s)
  /// @param name - name of the EventVar to be retrieved
  /// @param EVV - copy of the integer EventVarVect to be retrieved from the Event object
  ///
  void getEventVar(std::string name, EventVarVect<double> &EVV);


  ///
  /// Replace an EventVar<int> in the Event object with another EventVar<int>
  /// Throws an EventNameException if the EventVar does not exist in the Event object
  /// @param EV - integer EventVar to be added to the Event object
  ///
  void replaceEventVar(EventVar<int> &EV);

  ///
  /// Replace an EventVar<float> in the Event object with another EventVar<float>
  /// Throws an EventNameException if the EventVar does not exist in the Event object
  /// @param EV - float EventVar to be added to the Event object
  ///
  void replaceEventVar(EventVar<float> &EV);

  ///
  /// Replace an EventVar<double> in the Event object with another EventVar<double>
  /// Throws an EventNameException if the EventVar does not exist in the Event object
  /// @param EV - double EventVar to be added to the Event object
  ///
  void replaceEventVar(EventVar<double> &EV);

  ///
  /// Replace an EventVarVect<int> in the Event object with another EventVarVect<int>
  /// Throws an EventNameException if the EventVar does not exist in the Event object
  /// @param EV - EventVarVect to be added to the Event object
  ///
  void replaceEventVar(EventVarVect<int> &EVV);

  ///
  /// Replace an EventVarVect<float> in the Event object with another EventVarVect<float>
  /// Throws an EventNameException if the EventVar does not exist in the Event object
  /// @param EV - EventVarVect to be added to the Event object
  ///
  void replaceEventVar(EventVarVect<float> &EVV);

  ///
  /// Add an EventVarVect<double> to the Event object
  /// Replace an EventVarVect<float> in the Event object with another EventVarVect<float>
  /// Throws an EventNameException if the EventVar does not exist in the Event object
  /// @param EV - EventVarVect to be added to the Event object
  ///
  void replaceEventVar(EventVarVect<double> &EVV);




  ///
  /// Delete an EventVar<int> in the Event object
  /// Throws an EventNameException if the EventVar does not exist in the Event object
  /// @param EV - integer EventVar to be deleted from the Event object
  ///
  void deleteEventVar(EventVar<int> &EV);

  ///
  /// Delete an EventVar<float> in the Event object with another EventVar<float>
  /// Throws an EventNameException if the EventVar does not exist in the Event object
  /// @param EV - float EventVar to be deleted from the Event object
  ///
  void deleteEventVar(EventVar<float> &EV);

  ///
  /// Delete an EventVar<double> in the Event object
  /// Throws an EventNameException if the EventVar does not exist in the Event object
  /// @param EV - double EventVar to be deleted from the Event object
  ///
  void deleteEventVar(EventVar<double> &EV);

  ///
  /// Delete an EventVarVect<int> in the Event object
  /// Throws an EventNameException if the EventVar does not exist in the Event object
  /// @param EV - EventVarVect to be deleted from the Event object
  ///
  void deleteEventVar(EventVarVect<int> &EVV);

  ///
  /// Delete an EventVarVect<float> in the Event object
  /// Throws an EventNameException if the EventVar does not exist in the Event object
  /// @param EV - EventVarVect to be deleted from the Event object
  ///
  void deleteEventVar(EventVarVect<float> &EVV);

  ///
  /// Delete an EventVarVect<float> in the Event object
  /// Throws an EventNameException if the EventVar does not exist in the Event object
  /// @param EV - EventVarVect to be deleted from the Event object
  ///
  void deleteEventVar(EventVarVect<double> &EVV);

  ///
  /// Delete an EventVar or EventVarVect in the Event object
  /// Throws an EventNameException if the EventVar does not exist in the Event object
  /// @param name - name of EventVar or EventVarVect to be deleted from the Event object
  ///
  void deleteEventVar(std::string name);




  ///
  /// Assignment operator that assigns the values in an Event to 
  /// the data elements of a second Event
  ///
  Event& operator = (const Event& a);

  ///
  /// Set the EventNumber property to \c en
  /// @param en - set Event Number to this
  ///
  void setEventNumber(int en)              {EventNumber = en;}

  ///
  /// Set the OrbitNumber property to \c on
  /// @param on - set Orbit Number to this
  ///
  void setOrbitNumber(int on)              {OrbitNumber = on;}

  ///
  /// Set the Sunrise Sunset flag property to \c flag
  /// @param flag - set Sunrise / Sunset flag to this
  ///
  void setSRSSFlag(char flag)              {SR_SS_Flag  = flag;}

  ///
  /// Set the Event Start Time property to \c start
  /// @param start - Event Start Time
  ///
  void setEventStartTime(double start)     {EventStartTime = start;}

  ///
  /// Set the Event Stop Time property to \c stop
  /// @param stop - Event Stop Time
  ///
  void setEventStopTime(double stop)       {EventStopTime  = stop;}

  ///
  /// Set the Atmospheric Scan Start Time property to \c start
  /// @param start - Atmospheric Scan Start Time
  ///
  void setAtmosStartTime(double start)     {AtmosStartTime = start;}

  ///
  /// Set the Atmospheric Scan Stop Time property to \c stop
  /// @param stop - Atmospheric Scan Stop Time
  ///
  void setAtmosStopTime(double stop)       {AtmosStopTime  = stop;}

  ///
  /// Set the Solar Scan Start Time property to \c start
  /// @param start - Solar Scan Start Time
  ///
  void setSolarScanStartTime(double start) {SolarScanStartTime = start;}

  ///
  /// Set the Solar Scan Stop Time property to \c stop
  /// @param stop - Solar Scan Stop Time
  ///
  void setSolarScanStopTime(double stop)   {SolarScanStopTime  = stop;}

  ///
  /// Set the 83km tangenet point Latittude  property to \c lat
  /// @param lat - latitude of the 83km tangent point
  ///
  void setLatitude83km(double lat)         {Latitude83km   = lat;}

  ///
  /// Set the 83km tangenet point Longitude  property to \c lon
  /// @param lon - longitude of the 83km tangent point
  ///
  void setLongitude83km(double lon)        {Longitude83km  = lon; }

  ///
  /// Print the Event object properties to \c cerr
  ///
  void PrintEventProperties();

  ///
  /// Get the Event Number property
  ///
  int   getEventNumber()         {return EventNumber;}

  ///
  /// Get the Orbit Number property
  ///
  int   getOrbitNumber()         {return OrbitNumber;}

  ///
  /// Get the Sunrise / Sunset Flag property
  ///
  char  getSRSSFlag()            {return SR_SS_Flag;}

  ///
  /// Get the Event Start Time property
  ///
  double getEventStartTime()     {return EventStartTime;}

  ///
  /// Get the Event Stop Time property
  ///
  double getEventStopTime()      {return EventStopTime;}

  ///
  /// Get the Atmosperhic Scan Start Time property
  ///
  double getAtmosStartTime()     {return AtmosStartTime;}

  ///
  /// Get the Atmospheric Scan Stop Time property
  ///
  double getAtmosStopTime()      {return AtmosStopTime;}

  ///
  /// Get the Solar Scan Start Time property
  ///
  double getSolarScanStartTime() {return SolarScanStartTime;}

  ///
  /// Get the Solar Scan Stop Time property
  ///
  double getSolarScanStopTime()  {return SolarScanStopTime;}

  ///
  /// Get the 83km tangent point Latitude property
  ///
  double getLatitude83km()       {return Latitude83km;}

  ///
  /// Get the 83km tangent point Longitude property
  ///
  double getLongitude83km()      {return Longitude83km;}

private:

  ///
  /// Common initialization routine for the Event object
  ///
  void   init();

  ///
  /// Event Log enabled / disabled flag property
  ///
  bool   EventLogEnabled;

  ///
  /// Event Log time stamp enabled / disabled flag property
  ///
  bool   TimeStampEnabled;

  ///
  /// Event Number property
  ///
  int    EventNumber;

  ///
  /// Orbit Number property
  ///
  int    OrbitNumber;

  ///
  /// Sunrise / Sunset flag property
  ///
  char   SR_SS_Flag;

  ///
  /// Event Start Time property
  ///
  double EventStartTime;

  ///
  /// Event Stop Time property
  ///
  double EventStopTime;

  ///
  /// Atmospheric Scan Start Time property
  ///
  double AtmosStartTime;

  ///
  /// Atmospheric Scan Stop Time property
  ///
  double AtmosStopTime;

  ///
  /// Solar Scan Stop Time property
  ///
  double SolarScanStartTime;

  ///
  /// Solar Scan Stop Time property
  ///
  double SolarScanStopTime;

  ///
  /// 83km tangent point Latitude property
  ///
  double Latitude83km;

  ///
  /// 83km tangent point Longitude property
  ///
  double Longitude83km;

  ///
  /// Map of Integer EventVar objects
  ///
  std::map<std::string, EventVarVect<int> *>     intEventVarMap;

  ///
  /// Map of float EventVar objects
  ///
  std::map<std::string, EventVarVect<float> *>   floatEventVarMap;

  ///
  /// Map of double EventVar objects
  ///
  std::map<std::string, EventVarVect<double> *>  doubleEventVarMap;

  ///
  /// Event processing Log
  ///
  std::vector<std::string> EventLog;
  
  ///
  /// Event processing Log timestamp method
  ///
  std::string timestamp();

  ///
  /// Event processing Log output file
  ///
  std::ofstream logfile;

};



#endif