#pragma once
#include "InfluenceMap.h"
#include <BWAPI.h>
#include <cassert>

struct StructuralImportance
{
  int value;

  StructuralImportance() { reset(); }
  void reset() { value = 0; }

  bool isNull() const { return value <= 0; }

  void display(int x, int y, int w, int h, BWAPI::Player* player) const
  {
    unused(player);
    if (value > 0)
    {
      BWAPI::Color colour(0, 0, std::min(static_cast<int>(value / 500.f), 0xff));
      BWAPI::Broodwar->drawEllipseMap(x + w/2, y + h/2, w/2, h/2, colour, false);
    }
  }

  static void update(InfluenceMap<StructuralImportance>& map)
  {
    assert(map.getWidth()  == static_cast<unsigned int>(BWAPI::Broodwar->mapWidth())
        && map.getHeight() == static_cast<unsigned int>(BWAPI::Broodwar->mapHeight()));

    map.reset();

    const std::set<BWAPI::Unit*>& units = map.getPlayer()->getUnits();
    for(std::set<BWAPI::Unit*>::const_iterator i = units.begin(); i != units.end(); ++i)
    {
      BWAPI::Unit* unit = *i;
      BWAPI::UnitType type = unit->getType();
      const BWAPI::Position position = unit->getPosition();
      if (type.isBuilding())
      {
        // Lifted from BWAPI source code (GameImpl.cpp)
        int startX = (position.x() - type.dimensionLeft()) / TILE_SIZE;
        int endX   = (position.x() + type.dimensionRight() + TILE_SIZE - 1) / TILE_SIZE; // Division - round up
        int startY = (position.y() - type.dimensionUp()) / TILE_SIZE;
        int endY   = (position.y() + type.dimensionDown() + TILE_SIZE - 1) / TILE_SIZE;

        // Update the influence of all tiles the building is on
        for (int y = startY; y < endY; y++)
        {
          for (int x = startX; x < endX; x++)
          {
            StructuralImportance influence = map.getData(x, y);
            influence.value += type.buildScore();
            map.setInfluence(x, y, influence);
          }
        }
      }
    }
  }

  static const char* name() { return "Structural Importance"; }
};