#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#define NOMINMAX
#include <windows.h>
#include "SparAIFactory.h"
#include <Scenarios/Scenarios.h>
#include <SparAIModule.h>
#include <SituationAnalysis/Layer1GameState/Layer1GameState.h>
#include <SituationAnalysis/Layer2Cueing/Layer2Cueing.h>
#include <SituationAnalysis/Layer3TacticalRecognition/Layer3TacticalRecognition.h>
#include <SituationAnalysis/Layer4StrategicRecognition/Layer4StrategicRecognition.h>
#include <DecisionMaking/Layer1Reactive/Layer1FSM/Layer1FSM.h>
#include <DecisionMaking/Layer2Actions/Layer2Managers/Layer2Managers.h>
#include <DecisionMaking/Layer3Tactical/Layer3Script/Layer3Script.h>
#include <DecisionMaking/Layer4Strategic/Layer4Heuristic/Layer4Heuristic.h>

BOOL APIENTRY DllMain( HINSTANCE hModule, 
                      DWORD  ul_reason_for_call, 
                      LPVOID lpReserved
                      )
{
  //
  // When DLL_PROCESS_DETACH is called, the following conditions should hold:
  // - All threads have returned
  // - No additional synchronization (critical sections, mutexes, etc.) takes place
  //
  switch (ul_reason_for_call)
  {
  case DLL_PROCESS_ATTACH:
    BWAPI::BWAPI_init();
    break;
  case DLL_PROCESS_DETACH:
    break; 
  }
  return TRUE;
}

extern "C" __declspec(dllexport) BWAPI::AIModule* newAIModule(BWAPI::Game* game)
{
  BWAPI::Broodwar=game;

  BWAPI::Addon_Init();

  SparAIFactory factory;
  SparAIContainer* module = NULL;
  
  if (BWAPI::Broodwar->isReplay())
  {
    module = factory.instantiate<Layer1GameState, Layer2Cueing, Layer3TacticalRecognition, Layer4StrategicRecognition,
                                 InactiveLayer1, InactiveLayer2, InactiveLayer3, InactiveLayer4>(NULL);
  }
  else
  {
    module = Scenarios::instantiateSparAIForScenarios(factory);
    if (module == NULL)
    {
      module = factory.instantiate<Layer1GameState, Layer2Cueing, Layer3TacticalRecognition, Layer4StrategicRecognition,
                                   Layer1FSM, Layer2Managers, Layer3Script, Layer4Heuristic>(NULL);
      if (BWAPI::Broodwar->getGameType() != BWAPI::GameTypes::Use_Map_Settings)
      {
        BWAPI::Broodwar->setLocalSpeed(Config::getInstance().getDefaultSpeed());
      }
    }
  }

  return module;
}
