/*
 * This generates the basic AI base building plan for the future. It does not deal with base rebuilding, defenses, walls
 * Invoked when:
 * * receives a building with ConstructionYard=yes or a vehicle which deploys into that**
 * * a player disconnects from an MP game and an AI takes over (when does that happen?!)
 * * a map action #30 "Toggle Auto Base Building" fires**
 * 
 * ** only if the house doesn't have a base plan yet
 */
void HouseClass::GenerateAIBuildPlan() {

  unsigned int idxSide = this->Country->Side; // 0 - allied

  // Base stores BaseNodes , each BaseNode represents a building it will build
  // in SP maps, houses can fill this in the house's ini section
  this->Base->Nodes.Clear();

  // simply returns the index of this country in [Countries], so this is a bitfield with just n'th bit set
  unsigned int ownerBits = 1 << this->Country->ParentCountry->FindIndexOfName(); 

  DynamicVectorClass<BuildingTypeClass *> vec_CanBuildTypes;

  DynamicVectorClass<bool> vec_Booleans;

  foreach(vec_BuildingTypes as Bld) {
    if(!(ownerBits & Bld->Owner)
      || (Bld->AIBasePlanningSide != this->Country->Side && Bld->AIBasePlanningSide != -1)
      || !Bld->AIBuildThis
      || Bld->TechLevel > this->TechLevel
      || Bld->RequiredHouses != -1 && !(Bld->RequiredHouses & ownerBits)
      || Bld->ForbiddenHouses != -1 && (Bld->ForbiddenHouses & ownerBits)
    ) {
      continue;
    }

    if(!GameSettings->Superweapons && Bld->Superweapon != -1) {
      if(!Rules->BuildTech.Contains(Bld) && !vec_SuperWeaponTypes[Bld->Superweapon]->Type->DisableableFromShell) {
        continue;
      }
    }

    vec_CanBuildTypes.Append(Bld);
    vec_Booleans.Append(0);
  }

  DynamicVectorClass<BuildingTypeClass *> vec_PlanToBuildTypes;

  BuildingTypeClass *obj = this->FindFirstBuildableEntry(Rules->BuildConst);
  int idxOf = vec_CanBuildTypes.FindIndexOf(obj);
  if(idxOf != -1) {
    vec_Booleans[idxOf] = 1;
    vec_PlanToBuildTypes.Append(obj);
  }

  obj = this->FindFirstBuildableEntry(Rules->BuildPower);
  idxOf = vec_CanBuildTypes.FindIndexOf(obj);
  if(idxOf != -1) {
    vec_Booleans[idxOf] = 1;
    vec_PlanToBuildTypes.Append(obj);
  }

  obj = this->FindFirstBuildableEntry(Rules->BuildBarracks);
  idxOf = vec_CanBuildTypes.FindIndexOf(obj);
  if(idxOf != -1) {
    BuildingTypeClass *tmp = vec_CanBuildTypes[0];
    vec_CanBuildTypes[0] = obj;
    vec_CanBuildTypes[idxOf] = tmp;
    vec_Booleans[idxOf] = vec_Booleans[0];
    vec_Booleans[0] = 0;
  }

  obj = this->FindFirstBuildableEntry(Rules->BuildWeapons);
  idxOf = vec_CanBuildTypes.FindIndexOf(obj);
  if(idxOf != -1) {
    BuildingTypeClass *tmp = vec_CanBuildTypes[1];
    vec_CanBuildTypes[1] = obj;
    vec_CanBuildTypes[idxOf] = tmp;
    vec_Booleans[idxOf] = vec_Booleans[1];
    vec_Booleans[1] = 0;
  }

  int remainingTypes = vec_CanBuildTypes.Length - 1;
  while(remainingTypes > 0) {

    int idxGAPLUG = -1;
    bool foundSomething = 0;

    for(int j = 0; j < vec_CanBuildTypes.Length; ++j) {
      if(vec_Booleans[j]) {
        continue;
      }
      BuildingTypeClass *curType = vec_CanBuildTypes[j];
      if("GAPLUG".equals(curType->ID)) {
        idxGAPLUG = i;
      } else {
        if(this->CanBuildItemGivenThesePrereqs(curType, vec_PlanToBuildTypes)) {
          vec_Booleans[j] = 1;
          vec_PlanToBuildTypes.Append(curType);
          foundSomething = 1;
          --remainingTypes;
        }
      }
    }

    if(!foundSomething && idxGAPLUG != -1) {
      vec_PlanToBuildTypes.Append(vec_CanBuildTypes[idxGAPLUG]);
      vec_Booleans[idxGAPLUG] = 1;
      --remainingTypes;
    }
  }

  UnitTypeClass *harv = NULL;
  foreach(Rules->HarvesterUnit as curHarv) {
    if(curHarv->Owner & houseBits) {
      harv = curHarv;
      break;
    }
  }

  int countExtraRefineries;
  if(harv) {
    countExtraRefineries = Rules->AIExtraRefineries[this->AIDifficulty];
  } else {
    countExtraRefineries = Rules->AISlaveMinerNumber[this->AIDifficulty];
  }

  BuildingTypeClass *ref = this->FindFirstBuildableEntry(Rules->BuildRefinery);
  if(vec_PlanToBuildTypes.FindIndexOf(ref) != -1) {
    while(countExtraRefineries--) {
      int idxRand = RandomRanged(0, vec_PlanToBuildTypes.Length - 1);
      vec_PlanToBuildTypes.InsertAtPosition(idxRand, ref);
    }
  }

  DynamicVectorClass<BuildingTypeClass *> vec_FinalTypes;

  vec_FinalTypes.Append(vec_PlanToBuildTypes[0]);
  vec_FinalTypes.Append(vec_PlanToBuildTypes[1]);
  vec_FinalTypes.Append(vec_PlanToBuildTypes[2]);
  for(int j = 3; j < vec_PlanToBuildTypes.Length; ++j) {
    vec_FinalTypes.Append(vec_PlanToBuildTypes[j]);
  }

  int countBaseDefenses = 0;
  switch(this->Country->Side) {
    case 0:
      countBaseDefenses = Rules->AlliedBaseDefenseCounts[this->AIDifficulty];
      break;
    case 1:
      countBaseDefenses = Rules->SovietBaseDefenseCounts[this->AIDifficulty];
      break;
    case 2:
      countBaseDefenses = Rules->ThirdBaseDefenseCounts[this->AIDifficulty];
      break;
  }

  for(int j = 0; j < countBaseDefenses; ++j) {
    int idxRand = RandomRanged(3, vec_FinalTypes.Length - 1);
    vec_FinalTypes.InsertAtPosition(idxRand, -1); // special case hack, stands for buildings from PrerequisitePower
  }

  for(int k = 0; k < vec_FinalTypes.Length; ++k) {
    BuildingTypeClass *curType = vec_FinalTypes[k];

/*
struct BaseNode {
 int BuildingTypeIndex;
 CoordStruct Position;
 bool unknown1;
 int unknown2;
}
 */

    BaseNode *newNode = new BaseNode();
    newNode->unknown1 = 0;
    newNode->unknown2 = 0;
    if((signed int)curType >= 0 || (signed int)curType < -4) {
      newNode->BuildingTypeIndex = curType->IndexInArray;
      newNode->Position = {0, 0};
      this->Base->Nodes.Append(newNode);
    } else {
      BaseNode *newNode = new BaseNode();
      newNode->BuildingTypeIndex = curType;
      newNode->Position = {0, 0};
      this->Base->Nodes.Append(newNode);
    }
  }
}