#pragma once
#include "../../Interface/Actions/Defend.h"
#include "../../../Layer1Reactive/Layer1FSM/Behaviors/Protoss/EngageEnemies/GroupAttack/GroupAttackBehavior.h"
#include "../../../../Utils/Process/ProcessContainer.h"
#include "../../../../PerceptualState/Locations/Static/AutoPopulated/AutoPopulatedLocation.h"
#include "L2GroupTacticalAction.h"

// TODO: possibly more than two locations so units can patrol?

class L2Defend : public virtual Defend, public L2GroupTacticalAction
{
public:
  L2Defend(const Process* parent, unsigned int priority, const PersistentUnitGroup* initialGroup, Location* location)
    : Defend(parent, priority, initialGroup, location)
    , L2GroupTacticalAction(parent, priority, initialGroup)
    , GroupTacticalAction(parent, priority, initialGroup)
    , TacticalAction(parent, priority)
    , Process(parent)
    , m_groupAttackBehavior(*this)
    , m_onEnemyAddedEventHandler(*this)
    //, m_onUnitAddedEventHandler(*this)
    , m_onEnemyRemovedEventHandler(*this)
    , m_currentLocation(*this, NULL)
    , m_currentPosition(BWAPI::Positions::Invalid)
  {
  }

  ~L2Defend()
  {
  }

protected:
  virtual void onStartImplementation();
  virtual void onCancelImplementation();
  virtual void onEndImplementation();

  virtual void onUnitAddedToGroup(void*, BWAPI::Unit* unit);
  virtual void onUnitRemovedFromGroup(void*, BWAPI::Unit* unit);

  //void onTerminate(void* data);
  void onEnemyAdded(void* data, UnitRecord* unitRecord);
  //void onUnitAdded(void* data, UnitRecord*);
  void onEnemyRemoved(void* data, UnitRecord* unitRecord, BWAPI::UnitType previousUnitType, BWAPI::Player* previousPlayer);

  Region* regionAttackedByEnemy();

  void subscribeAllEnemyUnitAdded();
  void unsubscribeAllEnemyUnitAdded();
  //void subscribeEnemyUnitAdded(AutoPopulatedLocation* cl);
  BWAPI::Position getDefendPosition() const;

private:
  //Event<boost::tuples::tuple<UnitRecord*>>::SubscriberID m_onUnitAddedSubscriberId;
  //Event<boost::tuples::tuple<UnitRecord*>>::SubscriberID m_onEnemyAddedSubscriberId;
  Event<boost::tuples::tuple<UnitRecord*, BWAPI::UnitType, BWAPI::Player*>>::SubscriberID m_onEnemyRemovedSubscriberId;
  //Event<boost::tuples::tuple<>>::SubscriberID m_onTerminateSubscriberId;

  //EVENT_HANDLER1(L2Defend, onUnitAdded, UnitRecord*) m_onUnitAddedEventHandler;
  EVENT_HANDLER1(L2Defend, onEnemyAdded, UnitRecord*) m_onEnemyAddedEventHandler;
  EVENT_HANDLER3(L2Defend, onEnemyRemoved, UnitRecord*, BWAPI::UnitType, BWAPI::Player*) m_onEnemyRemovedEventHandler;
  //EVENT_HANDLER(L2Defend, onTerminate) m_onTerminateEventHandler;

  ProcessContainer<GroupAttackBehavior> m_groupAttackBehavior;
  bool m_waiting;
  AutoPtr<AutoPopulatedLocation> m_currentLocation;
  BWAPI::Position m_currentPosition;
  UnitRecord* m_currentTarget;
  std::map<AutoPopulatedLocation*,Event<boost::tuples::tuple<UnitRecord*>>::SubscriberID> m_mapSubscription;
};
