#pragma once
#include "../../../Layer1Reactive/Layer1FSM/Behaviors/General/GatherMineralsBehavior.h"
#include "../../../Layer1Reactive/Layer1FSM/Behaviors/General/Move/GroupMoveBehavior.h"
#include "../../Interface/Actions/Collect.h"
#include "L2GroupTacticalAction.h"

class L2Collect : public virtual Collect, public L2GroupTacticalAction
{
public:
  L2Collect(const Process* parent, unsigned int priority, const PersistentUnitGroup* initialGroup, BaseLocation* baseLocation)
    : Collect(parent, priority, initialGroup, baseLocation)
    , L2GroupTacticalAction(parent, priority, initialGroup)
    , GroupTacticalAction(parent, priority, initialGroup)
    , TacticalAction(parent, priority)
    , Process(parent)
  {
  }

};

class L2CollectMinerals : public virtual CollectMinerals, public L2Collect
{
public:
  L2CollectMinerals(const Process* parent, unsigned int priority, const PersistentUnitGroup* initialGroup, BaseLocation* baseLocation)
    : CollectMinerals(parent, priority, initialGroup, baseLocation)
    , L2Collect(parent, priority, initialGroup, baseLocation)
    , Collect(parent, priority, initialGroup, baseLocation)
    , GroupTacticalAction(parent, priority, initialGroup)
    , TacticalAction(parent, priority)
    , Process(parent)
    , m_movingGroup("Collect Mineral, Moving group")
    , m_gatheringGroup("Collect Mineral, Gathering group")
    , m_gatherBehavior(this, priority, &m_gatheringGroup, baseLocation)
    , m_gatherBehaviorTerminatedEventHandler(*this)
    , m_moveBehavior(NULL)
    , m_unitAtDestinationEventHandler(*this)
    , m_moveBehaviorTerminatedEventHandler(*this)
  {
  }

private:
  // Groups must be declared before their behaviors !
  PersistentUnitGroup m_movingGroup;
  PersistentUnitGroup m_gatheringGroup;

  GatherMineralsBehavior m_gatherBehavior;
  EVENT_HANDLER(L2CollectMinerals, onGatherBehaviorTerminated) m_gatherBehaviorTerminatedEventHandler;
  Event<boost::tuples::tuple<>>::SubscriberID m_gatherBehaviorTerminatedSubscriberId;

  GroupMoveBehavior* m_moveBehavior;
  EVENT_HANDLER1(L2CollectMinerals, onUnitAtDestination, BWAPI::Unit*) m_unitAtDestinationEventHandler;
  Event<boost::tuples::tuple<BWAPI::Unit*>>::SubscriberID m_unitAtDestinationSubscriberId;
  EVENT_HANDLER(L2CollectMinerals, onMoveBehaviorTerminated) m_moveBehaviorTerminatedEventHandler;
  Event<boost::tuples::tuple<>>::SubscriberID m_moveBehaviorTerminatedSubscriberId;

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 startMoveBehavior();

  void onUnitAtDestination(void* data, BWAPI::Unit* unit);
  void onMoveBehaviorTerminated(void* data);
  void onGatherBehaviorTerminated(void* data);
};

class L2CollectGas : public virtual CollectGas, public L2Collect
{
public:
  L2CollectGas(const Process* parent, unsigned int priority, const PersistentUnitGroup* initialGroup, BaseLocation* baseLocation)
    : CollectGas(parent, priority, initialGroup, baseLocation)
    , L2Collect(parent, priority, initialGroup, baseLocation)
    , Collect(parent, priority, initialGroup, baseLocation)
    , GroupTacticalAction(parent, priority, initialGroup)
    , TacticalAction(parent, priority)
    , Process(parent)
  {
  }

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

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