#pragma once
#include "../../DecisionMaking/Layer1Reactive/Layer1FSM/Behaviors/Protoss/CorsairHarassmentBehavior.h"
#include "../Scenario.h"
#include <map>
#include <vector>

class CorsairScenario : public Scenario<CorsairScenario>
{
public:
  typedef std::map<BWAPI::Unit *, BWAPI::OnIndividualUnitDestroy::SubscriberID> OverlordMap;
  
  struct OverlordGroup
  {
    AutoPtr<Location> area;
    OverlordMap overlords;
    Behavior * behavior;
    int count;

    OverlordGroup(Location * loc, int c) : area(this, loc), count(c), behavior(0) {}
  };

private:
  BWAPI::Unit * m_corsair;
  std::vector<OverlordGroup> m_overlords;

  bool m_isEnded;
  EVENT_HANDLER(CorsairScenario, onOverlordDestroyed) m_onOverlordDestroyedHandler;
  
  std::vector<OverlordGroup>::iterator m_current;

  std::vector<OverlordGroup>::iterator findOverlord(BWAPI::Unit * ov, OverlordMap::iterator &subIt);
  void initChallenges();

  EVENT_HANDLER1(CorsairScenario, onUnitDetected, BWAPI::Unit*) m_unitDetectedHandler;
	Event<boost::tuple<BWAPI::Unit*>>::SubscriberID m_unitDetectEventID;
  void onUnitDetected(void*, BWAPI::Unit* unit);

public:
  CorsairScenario() : 
      m_onOverlordDestroyedHandler(*this), 
      m_unitDetectedHandler(*this),
      m_isEnded(false) {}

  void onOverlordDestroyed(void*);

  void onEnd();
  void nextChallenge();

  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 << "Corsair Scenario";
  }
};