#pragma once
#include "../../Interface/Actions/Build.h"
#include "../../../Layer1Reactive/Layer1FSM/Behaviors/General/BuildBehavior.h"
#include "../../../../Utils/Process/ProcessContainer.h"
#include "L2BuildingPlacer.h"
#include "L2GroupTacticalAction.h"

class L2Build : public virtual Build, public L2GroupTacticalAction
{
public:
  /**
   * @brief Instantiates a Build action.
   * @param parent The parent of the action.
   * @param priority The priority of the action.
   * @param location The location at which the building should be constructed.
   * @param buildingType The type of building to construct.
   */
  L2Build(const Process* parent, unsigned int priority, AutoPopulatedLocation* location, BWAPI::UnitType buildingType);

  virtual ActionResources getPendingResourcesConsumption() const
  {
    if(m_building == NULL)
    {
      return ActionResources(Resources(m_buildingType));
    }
    else
    {
      return ActionResources(0,0,0);
    }
  }

  virtual UnitRecordGroup _getUnitsInvolved() const
  {
    UnitRecordGroup unitsInvolved = Build::_getUnitsInvolved(); 
    if(m_building != NULL)
      unitsInvolved.insert(m_building);
    return unitsInvolved;
  }

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 onUnitTypeCreatableChanged(void*, const UnitTypeObject* unitTypeObject);
  void onResourcesAllocated(void*, BWAPI::Unit* unit);
  void onUnitBehaviorTerminated(void*);
  void onFrame();
  void onUnitCompleted(void*, BWAPI::Unit* unit);
  void onUnitDestroyed(void*);

  void initiateBuildBehavior();
  BWAPI::Unit* findBuildProbe(BWAPI::TilePosition tile) const;

  BWAPI::Unit* m_worker;
  BWAPI::TilePosition m_buildTile;
  BWAPI::Unit* m_building;

  ProcessContainer<BuildBehavior> m_buildBehavior;
  Layer2ManagersBase::ResourcesRequest m_resourcesRequest;
  Event<boost::tuples::tuple<const UnitTypeObject*>>::SubscriberID m_unitTypeCreatableChangedSubscriberId;
  Event<boost::tuples::tuple<BWAPI::Unit*>>::SubscriberID m_unitCompletedSubscriberId;
  Event<boost::tuples::tuple<>>::SubscriberID m_unitDestroyedSubscriberId;
  
  SCHEDULER_EVENT_HANDLER(L2Build, onFrame) m_frameEvent;
  EVENT_HANDLER1(L2Build, onUnitTypeCreatableChanged, const UnitTypeObject*) m_unitTypeCreatableChangedEventHandler;
  EVENT_HANDLER(L2Build, onUnitDestroyed) m_unitDestroyedEventHandler;
  EVENT_HANDLER1(L2Build, onResourcesAllocated, BWAPI::Unit*) m_resourceAllocatedEventHandler;
  EVENT_HANDLER(L2Build, onUnitBehaviorTerminated) m_unitBehaviorTerminatedEventHandler;
  EVENT_HANDLER1(L2Build, onUnitCompleted, BWAPI::Unit*) m_unitCompletedEventHandler;
};
