#include <time.h>
#include <math.h>
#include <vector>
#include <string>
#include <sstream>
#include <limits>
#include <algorithm>

#include <conio.h>
#include <stdio.h>
#include <ctype.h>

using namespace std;
#include "TinyXML/tinyxml.h"

std::vector<unsigned char>   listCollisions;
std::vector<unsigned char>   listObjects;
std::vector<unsigned char>   listTiles;
std::vector<unsigned char>   listBack;

int map_width  = 0;
int map_height = 0;

bool Utils_CompareStrings(const char *str1, const char *str2)
{
    bool result = false;

    int res = strcmp(str1, str2);

    if (res == 0)
        result = true;

    return result;
}

//-------------------------------------------------------------
void ProcessCollisions(TiXmlElement *layerDataElement)
{
    TiXmlElement *tileElement;
    tileElement = layerDataElement->FirstChildElement("tile");

    if (tileElement == NULL)
        return;

    while(tileElement)
    {
        unsigned char tileGID = atoi(tileElement->Attribute("gid"));

        listCollisions.push_back(tileGID);

        tileElement = tileElement->NextSiblingElement("tile");
    }
}

//-------------------------------------------------------------
void ProcessObjects(TiXmlElement *layerDataElement)
{
    TiXmlElement *tileElement;
    tileElement = layerDataElement->FirstChildElement("tile");

    if (tileElement == NULL)
        return;

    while(tileElement)
    {
        unsigned char tileGID = atoi(tileElement->Attribute("gid"));

        listObjects.push_back(tileGID);

        tileElement = tileElement->NextSiblingElement("tile");
    }
}

//-------------------------------------------------------------
void ProcessTiles(TiXmlElement *layerDataElement)
{
    TiXmlElement *tileElement;
    tileElement = layerDataElement->FirstChildElement("tile");

    if (tileElement == NULL)
        return;

    while(tileElement)
    {
        unsigned char tileGID = atoi(tileElement->Attribute("gid"));

        listTiles.push_back(tileGID);

        tileElement = tileElement->NextSiblingElement("tile");
    }
}

//-------------------------------------------------------------
void ProcessBack(TiXmlElement *layerDataElement)
{
    TiXmlElement *tileElement;
    tileElement = layerDataElement->FirstChildElement("tile");

    if (tileElement == NULL)
        return;

    while(tileElement)
    {
        unsigned char tileGID = atoi(tileElement->Attribute("gid"));

        listBack.push_back(tileGID);

        tileElement = tileElement->NextSiblingElement("tile");
    }
}

//-------------------------------------------------------------
bool Load(std::string sFilename)
{
    listCollisions.clear();
    listObjects.clear();
    listTiles.clear();
    listBack.clear();

	TiXmlDocument levelFile(sFilename.c_str());

    if (!levelFile.LoadFile())
		return false;

    TiXmlElement *mapElement;
	TiXmlElement *layerElement;

    mapElement   = levelFile.FirstChildElement("map");
    layerElement = mapElement->FirstChildElement("layer");

    map_width  = atoi(mapElement->Attribute("width"));
    map_height = atoi(mapElement->Attribute("height"));

    printf("map width: %d\n", map_width);
    printf("map height: %d\n", map_height);

    while(layerElement)
    {
		// Контейнер <data>
        TiXmlElement *layerDataElement;
        layerDataElement = layerElement->FirstChildElement("data");

        const char *nameLayer = layerElement->Attribute("name");

        if (Utils_CompareStrings(nameLayer, "collisions"))
            ProcessCollisions(layerDataElement);

        if (Utils_CompareStrings(nameLayer, "objects"))
            ProcessObjects(layerDataElement);

        if (Utils_CompareStrings(nameLayer, "tiles"))
            ProcessTiles(layerDataElement);

        if (Utils_CompareStrings(nameLayer, "back"))
            ProcessBack(layerDataElement);

        layerElement = layerElement->NextSiblingElement("layer");
    }

    return true;
}

void Save()
{
    FILE *file = NULL;

    file = fopen("level.dat", "wb");

    if (file != NULL)
    {
        size_t countCollisions = listCollisions.size();
        size_t countObjects    = listObjects.size();
        size_t countTiles      = listTiles.size();
        size_t countBack       = listBack.size();

        fwrite(&map_width, sizeof(map_width), 1, file);
        fwrite(&map_height, sizeof(map_height), 1, file);

        if (countCollisions > 0)
		{
			for (size_t i = 0; i < countCollisions; ++i)
                fwrite(&listCollisions[i], sizeof(listCollisions[i]), 1, file);
		}

		if (countObjects > 0)
		{
			for (size_t i = 0; i < countObjects; ++i)
                fwrite(&listObjects[i], sizeof(listObjects[i]), 1, file);
		}

		if (countTiles > 0)
		{
			for (size_t i = 0; i < countTiles; ++i)
                fwrite(&listTiles[i], sizeof(listTiles[i]), 1, file);
		}

		if (countBack > 0)
		{
			for (size_t i = 0; i < countBack; ++i)
                fwrite(&listBack[i], sizeof(listBack[i]), 1, file);
		}
    }

    fclose(file);
}

int main(int argc, char **argv)
{
    char ch;
    bool res = Load("level.tmx");

    if (res)
    {
        Save();
        printf("OK");
    }
    else printf("FALSE");

    // использование точки для остановки
    do
    {
        ch = getche();

        if (islower(ch))
             putchar(toupper(ch));
        else putchar (tolower(ch));
    } while (ch != '.');

    return 0;
}
