#include "freetypemodel.h"
#include "mainwindow.h"


TFreeTypeModel::TFreeTypeModel(QObject *parent) :
    QObject(parent)
  , FontFileName("")
{
    fontColor = Qt::white;
    backgroundColor = Qt::transparent;

    fontInited = false;

}

TFreeTypeModel::~TFreeTypeModel()
{

}

void TFreeTypeModel::SetMainWindow(MainWindow* aMainWindow)
{
    mainWindow = aMainWindow;
}


void TFreeTypeModel::ClearFontParamText()
{
    fontParamText.clear();
}

QColor TFreeTypeModel::GetBackgroundColor()
{
    return backgroundColor;
}

QColor TFreeTypeModel::GetFontColor()
{
    return fontColor;
}

void TFreeTypeModel::RenderFontSlot()
{
    ProcessFont();
}

void TFreeTypeModel::LoadFont()
{

    QFileDialog dialog(mainWindow);

    dialog.setNameFilter(tr("TTF (*.ttf)"));

    dialog.setFileMode(QFileDialog::ExistingFile);

    if (dialog.exec())
    {
        FontFileName = (dialog.selectedFiles())[0];

        QFileInfo fileInfo(FontFileName);

        emit SetFontNameTextSignal(fileInfo.fileName());
        //emit SetFontNameTextSignal(FontFileName);

        LoadFontFile();

    }
}

void TFreeTypeModel::SaveFont()
{
    QFileDialog dialog(mainWindow);

    dialog.setFileMode(QFileDialog::AnyFile);

    dialog.setAcceptMode(QFileDialog::AcceptSave);
    if (dialog.exec())
    {
        QString str = (dialog.selectedFiles())[0];
        mainWindow->Pixmap->save(str + ".png", "PNG");
        mainWindow->SaveOutputEdit(fontParamText, str + ".txt");

    }
}

void TFreeTypeModel::SelectBackgroundColorPressed()
{
    QColorDialog dialog(mainWindow);

    dialog.setOption(QColorDialog::ShowAlphaChannel);

    if (dialog.exec())
    {
        backgroundColor = dialog.currentColor();
        mainWindow->RefreshColorMarkers();
    }
}

void TFreeTypeModel::SelectFontColorPressed()
{
    QColorDialog dialog(mainWindow);

    dialog.setOption(QColorDialog::ShowAlphaChannel);

    if (dialog.exec())
    {
        fontColor = dialog.currentColor();
        mainWindow->RefreshColorMarkers();
    }
}

void TFreeTypeModel::LoadFontFile()
{
    try
    {
        if (fontInited)
        {
            DestroyFontFile();
        }

        int error = FT_Init_FreeType(&FreeTypeLibrary);

        if (error)
        {
            throw QString("FT_Init_FreeType failed");
        }

        emit SetLoadResultTextSignal("Successful");

        mainWindow->UnlockDrawButton();

        fontInited = true;
    }
    catch(QString errorString)
    {
        emit SetLoadResultTextSignal(errorString);
    }
}

void TFreeTypeModel::DestroyFontFile()
{
    FT_Done_FreeType(FreeTypeLibrary);
}


void TFreeTypeModel::ProcessAndDrawSymbol(unsigned long charcode, QImage& img, int& shiftX, int& shiftY)
{

    FT_Face face;

    int error = FT_New_Face(FreeTypeLibrary, FontFileName.toAscii(), 0, &face);

    if (error == FT_Err_Unknown_File_Format)
    {
        throw QString("FT_New_Face failed: FT_Err_Unknown_File_Format");
    }
    else if (error)
    {
        throw QString("FT_New_Face failed: other error");
    }

    //Not in use
    //int intervalX = mainWindow->GetIntervalX();
    //int intervalY = mainWindow->GetIntervalY();

    int faceWidth = mainWindow->GetFaceWidth();
    int faceHeight = mainWindow->GetFaceHeight();

    if (FT_Set_Pixel_Sizes(face, faceWidth, faceHeight))
    {
        throw QString("FT_Set_Pixel_Sizes failed");
    }

    unsigned int glyph_index = FT_Get_Char_Index( face, charcode );

    if (FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER))
    {
        throw QString("FT_Load_Glyph failed");
    }

    FT_Glyph_Metrics metrics = face->glyph->metrics;

    int internalShiftY = mainWindow->GetFaceHeight() - metrics.horiBearingY / 64;
    int internalShiftX = metrics.horiBearingX / 64;

    int bitmapWidth = face->glyph->bitmap.width;
    int bitmapHeight = face->glyph->bitmap.rows;

    int oldShiftX = shiftX;
    int oldShiftY = shiftY;

    int advance = face->glyph->advance.x / 64;

    ProcessSymbol(face, charcode, shiftX, shiftY);

    for (int i=0; i<bitmapWidth; i++)
    {
        for (int j=0; j<bitmapHeight; j++)
        {
            unsigned char c = face->glyph->bitmap.buffer[(i+j*face->glyph->bitmap.width)];
            QColor finalColor;


            finalColor.setRed(backgroundColor.red()*(1.f - c/255.f) + (fontColor.red()) * (c/255.f));
            finalColor.setGreen(backgroundColor.green()*(1.f - c/255.f) + (fontColor.green()) * (c/255.f));
            finalColor.setBlue(backgroundColor.blue()*(1.f - c/255.f) + (fontColor.blue()) * (c/255.f));
            finalColor.setAlpha(backgroundColor.alpha()*(1.f - c/255.f) + (fontColor.alpha()) * (c/255.f));

            img.setPixel(i+oldShiftX,
                         j+oldShiftY+internalShiftY,
                         finalColor.rgba());
        }
    }

    float areaWidth = mainWindow->GetAreaWidth();
    float areaHeight = mainWindow->GetAreaHeight();

    QString qstr = QString::number(charcode) + " "
            + QString::number(oldShiftX / areaWidth) + " "
            + QString::number(oldShiftY / areaHeight) + " "
            + QString::number(internalShiftX / areaWidth) + " "
            + QString::number(internalShiftY / areaHeight) + " "
            + QString::number(bitmapWidth / areaWidth) + " "
            + QString::number(bitmapHeight / areaHeight) + " "
            + QString::number(advance / areaWidth);


    fontParamText.push_back(qstr);

    FT_Done_Face(face);
}



void TFreeTypeModel::ProcessSymbol(FT_Face& face, unsigned long charcode, int& shiftX, int& shiftY)
{

    int intervalX = mainWindow->GetIntervalX();
    int intervalY = mainWindow->GetIntervalY();

    int faceWidth = mainWindow->GetFaceWidth();
    int faceHeight = mainWindow->GetFaceHeight();

    int error = FT_Set_Pixel_Sizes(face, faceWidth, faceHeight);

    if (error)
    {
        throw QString("FT_Set_Pixel_Sizes failed");
    }

    unsigned int glyph_index = FT_Get_Char_Index(face, charcode);


    error = FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER);


    if (error)
    {
        throw QString("FT_Set_Pixel_Sizes failed");
    }

    int bitmapWidth = face->glyph->bitmap.width;

    if (shiftX + 2*(bitmapWidth + intervalX)+intervalX >= mainWindow->GetAreaWidth())
    {
        shiftX = intervalX;
        shiftY += mainWindow->GetFaceHeight() + intervalY;
    }
    else
    {
        shiftX += bitmapWidth + intervalX;
    }
}



void TFreeTypeModel::ProcessFont()
{
    try
    {

        mainWindow->RefreshSheetHeightWidth();

        QImage img(mainWindow->GetAreaWidth(), mainWindow->GetAreaHeight(), QImage::Format_ARGB32);

        img.fill(backgroundColor.rgba());

        int intervalX = mainWindow->GetIntervalX();
        int intervalY = mainWindow->GetIntervalY();

        int shiftX = intervalX;
        int shiftY = intervalY;

        QString str = mainWindow->GetSymbolList();


        ClearFontParamText();


        for (int i=0; i<str.count(); i++)
        {
            unsigned long ch = str[i].unicode();
            ProcessAndDrawSymbol(ch, img, shiftX, shiftY);
        }

        //mainWindow->Pixmap->convertFromImage(img, Qt::DiffuseAlphaDither);
        mainWindow->Pixmap->convertFromImage(img/*, Qt::DiffuseAlphaDither*/);

        emit InvalidateSignal();
        emit SetLoadResultTextSignal("Successful");

        mainWindow->UnlockSaveButton();
    }
    catch(QString errorString)
    {
        emit SetLoadResultTextSignal(errorString);
    }
}
