#include "TextureSheet.h"


bool pixmapSortFunc(const std::pair<QString, boost::shared_ptr<QPixmap>>& pixmap1, const std::pair<QString, boost::shared_ptr<QPixmap>>& pixmap2)
{
    return pixmap1.second->width() * pixmap1.second->height() > pixmap2.second->width() * pixmap2.second->height();
}


bool resultTexturePositionsSortFunc(const std::pair<QString, TexCoordRect>& result1, const std::pair<QString, TexCoordRect>& result2)
{
    return result1.first < result2.first;
}

void TextureSheet::Calculate(int width, int height)
{
    spaceAreaArr.clear();
    resultTexturePositions.clear();

    std::sort(pixmapArray.begin(), pixmapArray.end(), &pixmapSortFunc);

    resultPixmap = boost::shared_ptr<QPixmap>(new QPixmap(width, height));

    QColor transparentColor(0,0,0,0);

    resultPixmap->fill(transparentColor);


    spaceAreaArr.push_back(SpaceArea(0,0,width,height));

    QPainter p;


    p.begin(&(*resultPixmap));

    for (std::vector<std::pair<QString, boost::shared_ptr<QPixmap>>>::iterator pixmapItr = pixmapArray.begin(); pixmapItr != pixmapArray.end(); pixmapItr++)
    {

        boost::shared_ptr<QPixmap> selectedPixmap = pixmapItr->second;



        int foundIndex = -1;

        for (size_t i = 0; i < spaceAreaArr.size(); i++)
        {
            if (spaceAreaArr[i].Width >= selectedPixmap->width()
                    && spaceAreaArr[i].Height >= selectedPixmap->height()
                    && (foundIndex == -1 ||
                        spaceAreaArr[i].Width*spaceAreaArr[i].Height < spaceAreaArr[foundIndex].Width*spaceAreaArr[foundIndex].Height))
            {
                foundIndex = i;
            }
        }

        if (foundIndex != -1)
        {
            //split space

            SpaceArea rightSpaceArea(spaceAreaArr[foundIndex].posX + selectedPixmap->width(),
                                     spaceAreaArr[foundIndex].posY,
                                     spaceAreaArr[foundIndex].Width - selectedPixmap->width(),
                                     selectedPixmap->height());

            SpaceArea topSpaceArea(spaceAreaArr[foundIndex].posX,
                                     spaceAreaArr[foundIndex].posY + selectedPixmap->height(),
                                     spaceAreaArr[foundIndex].Width,
                                     spaceAreaArr[foundIndex].Height - selectedPixmap->height());


            p.drawPixmap(spaceAreaArr[foundIndex].posX, spaceAreaArr[foundIndex].posY, *selectedPixmap);

            TexCoordRect texCoordRect(spaceAreaArr[foundIndex].posX / static_cast<float>(width),
                                      spaceAreaArr[foundIndex].posY / static_cast<float>(height),
                                      (spaceAreaArr[foundIndex].posX + selectedPixmap->width()) / static_cast<float>(width),
                                      (spaceAreaArr[foundIndex].posY + selectedPixmap->height()) / static_cast<float>(height));

            texCoordRect.texCoordFromY = 1.f - texCoordRect.texCoordFromY;
            texCoordRect.texCoordToY = 1.f - texCoordRect.texCoordToY;

            float temp = texCoordRect.texCoordFromY;
            texCoordRect.texCoordFromY = texCoordRect.texCoordToY;
            texCoordRect.texCoordToY = temp;

            resultTexturePositions.push_back(std::pair<QString, TexCoordRect>(pixmapItr->first, texCoordRect));

            spaceAreaArr.erase(spaceAreaArr.begin() + foundIndex);
            spaceAreaArr.push_back(rightSpaceArea);
            spaceAreaArr.push_back(topSpaceArea);



        }
        else
        {
            throw std::runtime_error("Not enough space");
        }

    }

}

QString TextureSheet::GetCalculatedXml()
{
    QString result;

    result = "<TextureSheet>\n\t<TextureElements>\n";

    std::sort(imageNamesArray.begin(), imageNamesArray.end());

    std::sort(resultTexturePositions.begin(), resultTexturePositions.end(), &resultTexturePositionsSortFunc);

    for (size_t i = 0; i < imageNamesArray.size(); i++)
    {
        result += QString("\t\t<Texture><Name>%1</Name><TexCoordFrom x='%2' y='%3'/><TexCoordTo x='%4' y='%5'/></Texture>\n")
                .arg(imageNamesArray[i])
                .arg(QString::number(resultTexturePositions[i].second.texCoordFromX))
                .arg(QString::number(resultTexturePositions[i].second.texCoordFromY))
                .arg(QString::number(resultTexturePositions[i].second.texCoordToX))
                .arg(QString::number(resultTexturePositions[i].second.texCoordToY));
    }

    result += "\t</TextureElements>\n</TextureSheet>";

    return result;
}

void TextureSheet::Clear()
{
    spaceAreaArr.clear();
    resultTexturePositions.clear();
    pixmapArray.clear();
    imageNamesArray.clear();

    resultPixmap = boost::shared_ptr<QPixmap>(new QPixmap(4,4));

    QColor transparentColor(0,0,0,0);

    resultPixmap->fill(transparentColor);
}
