#pragma once
//#include "UnitData.h"
#include <BWAPI.h>
#include <list>

class UnitData;
/**
 * @brief Factory for instantiating UnitData. The only concrete factory is SparAIModule::SparUnitDataFactory.
 */
class UnitDataFactory
{
public:
  /**
   * @brief Instantiates data for a given unit.
   * @param unit A unit.
   * @return The unit data associated with this unit.
   */
  virtual UnitData* instantiateUnitData(BWAPI::Unit* unit) = 0;
};

/**
 * @brief The unit manager is responsible for providing per-unit data.
 *        Unit data is associated to each unit via the clientInfo pointer in BWAPI::Unit. If this pointer didn't exist
 *        some kind of hash map could be used.
 */
class UnitManager
{
public:
  /**
   * @brief Constructs a new UnitManager.
   */
  UnitManager()
    : m_factory(NULL)
  {}
  /**
   * @brief UnitManager's destructor. Deletes all pending unit data instances.
   */
  ~UnitManager();

  /**
   * @brief Adds data for the given unit.
   * @param unit The unit to add data for.
   */
  void addUnitData(BWAPI::Unit* unit);
  /**
   * @brief Removes data of the given unit. Assumes data was previously associated to the unit (which should always be the case).
   * @param unit The unit to remove the data of.
   */
  void removeUnitData(BWAPI::Unit* unit);
  /**
   * @brief Returns the data associated to a particular unit. Assumes data was previously added to the unit (which should always be the case).
   * @param unit The unit to retrieve the data for.
   * @return The data associated to the unit.
   */
  UnitData* getUnitData(BWAPI::Unit* unit)
  {
    return reinterpret_cast<UnitData*>(unit->getClientInfo());
  }

  void setUnitDataFactory(UnitDataFactory* unitDataFactory)
  {
    m_factory = unitDataFactory;
  }

private:
  /**
   * @brief Factory used to instantiate unit data.
   */
  UnitDataFactory* m_factory;

  /**
   * @brief List of unit data instances not yet deleted.
   */
  std::list<UnitData*> m_unitDataList; // Optimization: chain the UnitData to each other?
};