#pragma once
#include "../Scenario.h"
#include "../../DecisionMaking/Layer1Reactive/Layer1FSM/Behaviors/General/Scout/MotionScoutBehavior.h"
#include <fstream>
#include <deque>
#include <string>
#include <boost/lexical_cast.hpp>

/*
 * @brief functions and structures for the observerScenario
 */
namespace OSHF
{

  typedef std::deque<AutoPtr<Location>> LocationsList;
  typedef LocationsList::iterator LocationIterator; 

  const std::string OBS_FILENAME =  "ObserverTimer" + boost::lexical_cast<std::string>( time(0)) + ".csv";

 
  
  /*
   * @param pos the position container to fill
   *
   */
  void addLocation(LocationsList &pos, const Component &owner);

  struct ObserverState
  {
    BWAPI::Unit *_obs;
    LocationIterator _currentPos;    
    time_t _startTime;
    unsigned int _defi;
    lookahead_t _lookahead;

    ObserverState( BWAPI::Unit * unit, LocationIterator currentPos, unsigned int defi, lookahead_t lookahead)
      : _obs(unit), _currentPos(currentPos), _startTime(time(0)), _defi(defi), _lookahead(lookahead)
    {}

    ~ObserverState()
    {
      double t = difftime(time(0),_startTime);
      //Pas super.
      std::ofstream myfile;
      myfile.open(OBS_FILENAME.c_str(), std::ios::ate | std::ios::app | std::ios::out);
      assert(myfile.is_open());
      

      myfile<<_obs->getID()<<";"<<_lookahead<<";"<<_defi<<";"<<t<<std::endl;
      myfile.flush();
      myfile.close();
      _obs = 0;

    }
  };
}

class ObserverScenario : public Scenario<ObserverScenario>
{
  OSHF::LocationsList m_pos;
  std::vector<Process *> _behaviors;
  bool _isEnded;
  EVENT_HANDLER(ObserverScenario, onLocationReached) m_onTerminateHandler;

  static lookahead_t _lookahead[11];
  void sendNewDestination(OSHF::ObserverState* os);

public:
  ObserverScenario()
    :m_onTerminateHandler(*this)
    ,_isEnded(false)
  {
    OSHF::addLocation(m_pos, *this);
    
    //pas propre, sera retiré une fois les tests fait
    std::ofstream myfile;
    myfile.open(OSHF::OBS_FILENAME.c_str(),std::ios::app | std::ios::out);
    assert(myfile.is_open());
    myfile<<"Observer#;LookAhead;Defi;Time"<<std::endl;
    myfile.flush();
    myfile.close();
    
  }

  ~ObserverScenario();

  /**
   * Event handler to change the current behavior.
   **/
  void onLocationReached(void*);

  void onEnd();

  template <class SparAIFactory>
  SparAIContainer* instantiateSparAIImpl(SparAIFactory& sparFactory)
  {
    typedef SparAIModule<Layer1GameState, Layer2Cueing, Layer3TacticalRecognition, Layer4StrategicRecognition,
                         Layer1FSM, Layer2Managers, InactiveLayer3, InactiveLayer4> SPAR;

    SPAR* module = sparFactory.instantiate<Layer1GameState, Layer2Cueing, Layer3TacticalRecognition, Layer4StrategicRecognition,
                                           Layer1FSM, Layer2Managers, InactiveLayer3, InactiveLayer4>(this);

    return module;
  }


protected:
  virtual void onSparStarted(void* data);

  void _output(std::ostream &out) const
  {
    out << "Observer Scenario";
  }
};