/**
    This method loads the choam section of the INI file
*/
void INIMapEditorLoader::loadChoam()
{
    INIFile::KeyIterator iter;

    for(iter = inifile->begin("CHOAM"); iter != inifile->end("CHOAM"); ++iter) {
        std::string UnitStr = iter->getKeyName();

        Uint32 unitID = getItemIDByName(UnitStr);
        if((unitID == ItemID_Invalid) || !isUnit(unitID)) {
            logWarning(iter->getLineNumber(), "Invalid unit string: '" + UnitStr + "'");
            continue;
        }

        int num = iter->getIntValue(-2);
        if(num == -2) {
            logWarning(iter->getLineNumber(), "Invalid choam number!");
            continue;

        }

        if(num == -1) {
            num = 0;
        }

        pMapEditor->getChoam()[unitID] = num;
    }
}
/**
    This method loads the reinforcements from the [REINFORCEMENTS] section.
*/
void INIMapEditorLoader::loadReinforcements()
{
    INIFile::KeyIterator iter;

    for(iter = inifile->begin("REINFORCEMENTS"); iter != inifile->end("REINFORCEMENTS"); ++iter) {
		std::string strHouseName;
		std::string strUnitName;
		std::string strDropLocation;
		std::string strTime;
		std::string strPlus;

        if(splitString(iter->getStringValue(), 4, &strHouseName, &strUnitName, &strDropLocation, &strTime) == false) {
            if(splitString(iter->getStringValue(), 5, &strHouseName, &strUnitName, &strDropLocation, &strTime, &strPlus) == false) {
                logWarning(iter->getLineNumber(), "Invalid reinforcement string: " + iter->getKeyName() + " = " + iter->getStringValue());
                continue;
            }
        }

        int houseID = getHouseID(strHouseName);
        if(houseID == HOUSE_UNUSED) {
            // skip reinforcement for unused house
            continue;
        } else if(houseID == HOUSE_INVALID) {
            logWarning(iter->getLineNumber(), "Invalid house string: '" + strHouseName + "'!");
            continue;
        }

        Uint32 unitID = getItemIDByName(strUnitName);
        if((unitID == ItemID_Invalid) || !isUnit(unitID)) {
            logWarning(iter->getLineNumber(), "Invalid unit string: '" + strUnitName + "'!");
            continue;
        }

        DropLocation dropLocation = getDropLocationByName(strDropLocation);
        if(dropLocation == Drop_Invalid) {
            logWarning(iter->getLineNumber(), "Invalid drop location string: '" + strDropLocation + "'!");
            dropLocation = Drop_Homebase;
        }

        Uint32 droptime;
        if(!parseString(strTime, droptime)) {
            logWarning(iter->getLineNumber(), "Invalid drop time string: '" + strTime + "'!");
            continue;
        }

        bool bRepeat = (strTime.rfind('+') == (strTime.length() - 1)) || (strPlus == "+");

        pMapEditor->getReinforcements().push_back(ReinforcementInfo(houseID, unitID, dropLocation, droptime, bRepeat));
	}
}
void ObjectData::loadFromINIFile(std::string filename)
{
    SDL_RWops *file = pFileManager->OpenFile(filename);
    INIFile objectDataFile(file);
    SDL_RWclose(file);

    // load default structure values
    ObjectDataStruct structureDefaultData;
    structureDefaultData.hitpoints = objectDataFile.getIntValue("default structure", "HitPoints");
    structureDefaultData.price = objectDataFile.getIntValue("default structure", "Price");
    structureDefaultData.power = objectDataFile.getIntValue("default structure", "Power");
    structureDefaultData.viewrange = objectDataFile.getIntValue("default structure", "ViewRange");
    structureDefaultData.capacity = objectDataFile.getIntValue("default structure", "Capacity");
    structureDefaultData.weapondamage = objectDataFile.getIntValue("default structure", "WeaponDamage");
    structureDefaultData.weaponrange = objectDataFile.getIntValue("default structure", "WeaponRange");
    structureDefaultData.maxspeed = objectDataFile.getDoubleValue("default structure", "MaxSpeed");
    structureDefaultData.turnspeed = objectDataFile.getDoubleValue("default structure", "TurnSpeed");
    structureDefaultData.radius = objectDataFile.getIntValue("default structure", "Radius");
    structureDefaultData.buildtime = objectDataFile.getIntValue("default structure", "BuildTime");

    // load default unit values
    ObjectDataStruct unitDefaultData;
    unitDefaultData.hitpoints = objectDataFile.getIntValue("default unit", "HitPoints");
    unitDefaultData.price = objectDataFile.getIntValue("default unit", "Price");
    unitDefaultData.power = objectDataFile.getIntValue("default unit", "Power");
    unitDefaultData.viewrange = objectDataFile.getIntValue("default unit", "ViewRange");
    unitDefaultData.capacity = objectDataFile.getIntValue("default unit", "Capacity");
    unitDefaultData.weapondamage = objectDataFile.getIntValue("default unit", "WeaponDamage");
    unitDefaultData.weaponrange = objectDataFile.getIntValue("default unit", "WeaponRange");
    unitDefaultData.maxspeed = objectDataFile.getDoubleValue("default unit", "MaxSpeed");
    unitDefaultData.turnspeed = objectDataFile.getDoubleValue("default unit", "TurnSpeed");
    unitDefaultData.radius = objectDataFile.getIntValue("default unit", "Radius");
    unitDefaultData.buildtime = objectDataFile.getIntValue("default unit", "BuildTime");

    // set default values
    for(int i=0;i<ItemID_max;i++) {
        if(isStructure(i)) {
            data[i] = structureDefaultData;
        } else {
            data[i] = unitDefaultData;
        }
    }

    INIFile::SectionIterator iter;
    for(iter = objectDataFile.begin(); iter != objectDataFile.end(); ++iter) {
        std::string sectionName = iter->getSectionName();

        if(sectionName == "" || sectionName == "default structure" || sectionName == "default unit") {
            continue;
        }

        Uint32 itemID = getItemIDByName(sectionName);

        if(itemID == ItemID_Invalid) {
            std::cerr << "ObjectData::ObjectData(): \"" << sectionName << "\" is no valid unit/structure name!" << std::endl;
            continue;
        }

        ObjectDataStruct& defaultData = isStructure(itemID) ? structureDefaultData : unitDefaultData;

        data[itemID].hitpoints = objectDataFile.getIntValue(sectionName, "HitPoints", defaultData.hitpoints);
        data[itemID].price = objectDataFile.getIntValue(sectionName, "Price", defaultData.price);
        data[itemID].power = objectDataFile.getIntValue(sectionName, "Power", defaultData.power);
        data[itemID].viewrange = objectDataFile.getIntValue(sectionName, "ViewRange", defaultData.viewrange);
        data[itemID].capacity = objectDataFile.getIntValue(sectionName, "Capacity", defaultData.capacity);
        data[itemID].weapondamage = objectDataFile.getIntValue(sectionName, "WeaponDamage", defaultData.weapondamage);
        data[itemID].weaponrange = objectDataFile.getIntValue(sectionName, "WeaponRange", defaultData.weaponrange);
        data[itemID].maxspeed = objectDataFile.getDoubleValue(sectionName, "MaxSpeed", defaultData.maxspeed);
        data[itemID].turnspeed = objectDataFile.getDoubleValue(sectionName, "TurnSpeed", defaultData.turnspeed);
        data[itemID].radius = objectDataFile.getIntValue(sectionName, "Radius", defaultData.radius);
        data[itemID].buildtime = objectDataFile.getIntValue(sectionName, "BuildTime", defaultData.buildtime);
    }
}
/**
    This method loads the structures specified by the [Structures] section.
*/
void INIMapEditorLoader::loadStructures()
{
    int genID = -2;

    INIFile::KeyIterator iter;

    for(iter = inifile->begin("STRUCTURES"); iter != inifile->end("STRUCTURES"); ++iter) {
		std::string tmpkey = iter->getKeyName();
		std::string tmp = iter->getStringValue();

		if(tmpkey.find("GEN") == 0) {
			// Gen Object/Structure
			std::string PosStr = tmpkey.substr(3,tmpkey.size()-3);
            int pos;
            if(!parseString(PosStr, pos) || (pos < 0)) {
                logWarning(iter->getLineNumber(), "Invalid position string: '" + PosStr + "'!");
                continue;
            }

			std::string HouseStr, BuildingStr;
			splitString(tmp,2,&HouseStr,&BuildingStr);

			HOUSETYPE houseID = getHouseID(HouseStr);
			if(houseID == HOUSE_UNUSED) {
                // skip structure for unused house
                continue;
            } else if(houseID == HOUSE_INVALID) {
				logWarning(iter->getLineNumber(), "Invalid house string for '" + BuildingStr + "': '" + HouseStr + "'!");
				continue;
			}

			int itemID = getItemIDByName(BuildingStr);

			if((itemID == Structure_Slab1) || (itemID == Structure_Slab4) || (itemID == Structure_Wall)) {
			    pMapEditor->structures.push_back(MapEditor::Structure(genID, houseID, itemID, 256, Coord(getXPos(pos),getYPos(pos))));
			    genID--;
			} else {
			    logWarning(iter->getLineNumber(), "Invalid building string: '" + BuildingStr + "' for GEN-Placement!");
			    continue;
			}

		} else if(tmpkey.find("ID") == 0) {
		    // other structure
			int structureID = 0;
            parseString(tmpkey.substr(2), structureID);

			std::string HouseStr, BuildingStr, health, PosStr;
			splitString(tmp,6,&HouseStr,&BuildingStr,&health,&PosStr);

            int pos;
            if(!parseString(PosStr, pos) || (pos < 0)) {
                logWarning(iter->getLineNumber(), "Invalid position string for '" + BuildingStr + "': '" + PosStr + "'!");
                continue;
            }

			HOUSETYPE houseID = getHouseID(HouseStr);
            if(houseID == HOUSE_UNUSED) {
                // skip structure for unused house
                continue;
            } else if(houseID == HOUSE_INVALID) {
				logWarning(iter->getLineNumber(), "Invalid house string for '" + BuildingStr + "': '" + HouseStr + "'!");
				continue;
			}

            int iHealth;
            if(!parseString(health, iHealth) || (iHealth < 0) || (iHealth > 256)) {
                logWarning(iter->getLineNumber(), "Invalid health string: '" + health + "'!");
                iHealth = 256;
            }

			int itemID = getItemIDByName(BuildingStr);

			if((itemID == ItemID_Invalid) || !isStructure(itemID)) {
			    logWarning(iter->getLineNumber(), "Invalid building string: '" + BuildingStr + "'!");
			    continue;
			}

			pMapEditor->structures.push_back(MapEditor::Structure(structureID, houseID, itemID, iHealth, Coord(getXPos(pos),getYPos(pos))));
		} else {
            logWarning(iter->getLineNumber(), "Invalid structure key: '" + tmpkey + "'!");
            continue;
		}
	}
}
/**
    This method loads the units specified by the [Units] section.
*/
void INIMapEditorLoader::loadUnits()
{
    INIFile::KeyIterator iter;

    for(iter = inifile->begin("UNITS"); iter != inifile->end("UNITS"); ++iter) {
        if(iter->getKeyName().find("ID") == 0) {
            int unitID = 0;
            parseString(iter->getKeyName().substr(2), unitID);

            std::string HouseStr, UnitStr, health, PosStr, rotation, mode;
            splitString(iter->getStringValue(),6,&HouseStr,&UnitStr,&health,&PosStr,&rotation,&mode);

            HOUSETYPE houseID = getHouseID(HouseStr);
            if(houseID == HOUSE_UNUSED) {
                // skip unit for unused house
                continue;
            } else if(houseID == HOUSE_INVALID) {
                logWarning(iter->getLineNumber(), "Invalid house string for '" + UnitStr + "': '" + HouseStr + "'!");
                continue;
            }

            int pos;
            if(!parseString(PosStr, pos) || (pos < 0)) {
                logWarning(iter->getLineNumber(), "Invalid position string for '" + UnitStr + "': '" + PosStr + "'!");
                continue;
            }

            int angle;
            if(!parseString(rotation, angle) || (angle < 0) || (angle > 255)) {
                logWarning(iter->getLineNumber(), "Invalid rotation string: '" + rotation + "'!");
                angle = 64;
            }
            angle = (angle+16)/32;
            angle = ((NUM_ANGLES - angle) + 2) % NUM_ANGLES;


            int itemID = getItemIDByName(UnitStr);
            if((itemID == ItemID_Invalid) || !isUnit(itemID)) {
                logWarning(iter->getLineNumber(), "Invalid unit string: '" + UnitStr + "'!");
                continue;
            }

            int iHealth;
            if(!parseString(health, iHealth) || (iHealth < 0) || (iHealth > 256)) {
                logWarning(iter->getLineNumber(), "Invalid health string: '" + health + "'!");
                iHealth = 256;
            }

            ATTACKMODE attackmode = getAttackModeByName(mode);
            if(attackmode == ATTACKMODE_INVALID) {
                logWarning(iter->getLineNumber(), "Invalid attackmode string: '" + mode + "'!");
                attackmode = AREAGUARD;
            }

            if(itemID == Unit_Soldier || itemID == Unit_Saboteur || itemID == Unit_Trooper || itemID == Unit_Infantry || itemID == Unit_Troopers) {
                if(angle == UP) {
                    angle = UP;
                } else if (angle == DOWN) {
                    angle = DOWN;
                } else if (angle == LEFTUP || angle == LEFTDOWN || angle == LEFT) {
                    angle = LEFT;
                } else /*(angle == RIGHT)*/ {
                    angle = RIGHT;
                }
            }

            pMapEditor->units.push_back(MapEditor::Unit(unitID, houseID, itemID, iHealth, Coord(getXPos(pos),getYPos(pos)), (unsigned char) angle, attackmode));

        } else {
            logWarning(iter->getLineNumber(), "Invalid unit key: '" + iter->getKeyName() + "'!");
            continue;
        }
	}
}