/***************************************************************************
 *   Copyright 2007-2008 Wouter Haffmans <cheetah@simply-life.net>         *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU General Public License as        *
 *   published by the Free Software Foundation; either version 2 of        *
 *   the License or (at your option) version 3 or any later version        *
 *   accepted by the membership of KDE e.V. (or its successor approved     *
 *   by the membership of KDE e.V.), which shall act as a proxy            *
 *   defined in Section 14 of version 3 of the license.                    *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
 ***************************************************************************/

#include "kiddrawarea.h"

#include <QtGui/QVBoxLayout>
#include <QtGui/QHBoxLayout>
#include <QtGui/QGridLayout>
#include <QtGui/QMouseEvent>
#include <KFileDialog>
#include <KStandardDirs>

#include "canvas.h"
#include "simplecolorpick.h"
#include "simplewidthpick.h"
#include "palettemanagerxml.h"
#include "palettebutton.h"
#include "drawingreader.h"
#include "drawingwriter.h"

#include <QtDebug>
#include "themeloader.h"
#include <ksharedconfig.h>

KidDrawArea::KidDrawArea(QWidget *parent)
 : QWidget(parent)
{
    loadTheme();
    createCanvas();
    createPalette();
    createColorPicks();
    createWidthPicks();
    createImagePicks();
    createButtons();
    createLayout();

    setColor(m_palette->at(0));
    setLineWidth(3);
}


KidDrawArea::~KidDrawArea()
{
}

void KidDrawArea::loadTheme() {
    KSharedConfigPtr config = KGlobal::config();
    KConfigGroup generalGroup = config->group("General");
    QString themeName = generalGroup.readEntry("theme", "default");
    m_theme = new ThemeLoader(themeName, this);
}

void KidDrawArea::createCanvas()
{
    m_canvas = new Canvas(this);
    QPen pen = m_canvas->pen();
    pen.setJoinStyle(Qt::MiterJoin);
    m_canvas->setPen(pen);

    connect(this, SIGNAL(newPalette()),
            this, SLOT(updateCanvasColors()));
}

void KidDrawArea::createPalette()
{
    QString palettesFile = KStandardDirs::locate("appdata", "palettes.xml");
    KStandardDirs sdirs;
    QStringList dirs(sdirs.resourceDirs("data"));
    qDebug() << dirs;
    m_paletteManager = new PaletteManagerXML(palettesFile);
    m_paletteNumber = 0;
    m_maxTag = 0;

    Palette *p;
    p = NULL;

    if (m_paletteManager->countPalettes() > 0) {
        p = m_paletteManager->palettes().value(
            m_paletteManager->paletteNames().at(m_paletteNumber)
        );
    }

    if (p == NULL) {
        Color white, black;
        white.color = QColor(Qt::white);
        white.border = QColor(Qt::black);
        white.background = QColor(Qt::black);

        black.color = QColor(Qt::black);
        black.border = QColor(Qt::white);
        black.background = QColor(Qt::white);

        p = new Palette();
        p->append(white);
        p->append(black);
    }

    m_palette = new QVector<QRgb>();
    m_borderPalette = new QVector<QRgb>();
    m_backgroundPalette = new QVector<QRgb>();

    loadPalette(p);
}

void KidDrawArea::createColorPicks()
{
    m_colorPicksBoxLeft = new QVBoxLayout();
    m_colorPicksBoxRight = new QVBoxLayout();

    m_colorPicks = new QList<SimpleColorPick *>();

    connect(this, SIGNAL(newPalette()),
            this, SLOT(updatePicks()));

    updatePicks();
}

void KidDrawArea::createWidthPicks()
{
    m_widthPicksBox = new QHBoxLayout();

    m_widthPicks = new QList<SimpleWidthPick *>();

    SimpleWidthPick *curPick;
    QList<int> widths;
    widths.append(1);
    widths.append(3);
    widths.append(5);
    widths.append(10);
    widths.append(20);

    m_widthPicksBox->addStretch(1);
    for (QList<int>::const_iterator i = widths.constBegin();
         i != widths.constEnd(); ++i) {
        // Convert color to QColor (from QRgb), then create pick
        curPick = new SimpleWidthPick(*i);
        // Add pick to layout
        m_widthPicksBox->addWidget(curPick);
        // Add pick to list
        m_widthPicks->append(curPick);

        // Connect pick signal
        connect(curPick, SIGNAL(picked(int)),
                this, SLOT(setLineWidth(int)));
    }
    m_widthPicksBox->addStretch(1);
}

void KidDrawArea::createImagePicks()
{
    m_imagePicksBox = new QHBoxLayout();
}

void KidDrawArea::createButtons()
{
//     QPen pen(Qt::black, 3, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin);
//     QBrush brush(Qt::white);
//
//     m_leftPaletteButton = new TriangleButton(AbstractPolyButton::left,
//             pen, brush);
//     m_rightPaletteButton = new TriangleButton(AbstractPolyButton::right,
//             pen, brush);
//
//     connect(m_leftPaletteButton, SIGNAL(clicked()),
//             this, SLOT(previousPalette()));
//     connect(m_rightPaletteButton, SIGNAL(clicked()),
//             this, SLOT(nextPalette()));
//     m_leftPaletteButton = new PaletteButton("/home/cheetah/dev/kde/playground/edu/kiddraw/themes/default/kiddraw-buttons.svg", "paletteButtonLeft", this);
//     m_rightPaletteButton = new PaletteButton("/home/cheetah/dev/kde/playground/edu/kiddraw/themes/default/kiddraw-buttons.svg", "paletteButtonRight", this);
    m_leftPaletteButton = new PaletteButton(m_theme, "paletteButtonLeft", this);
    m_rightPaletteButton = new PaletteButton(m_theme, "paletteButtonRight", this);
    connect(m_leftPaletteButton, SIGNAL(clicked()),
            this, SLOT(previousPalette()));
    connect(m_rightPaletteButton, SIGNAL(clicked()),
            this, SLOT(nextPalette()));
}

void KidDrawArea::createLayout()
{
    m_layout = new QGridLayout(this);
    // Clear button: 0, 0
    // Image picker: 0, 1
    m_layout->addLayout(m_imagePicksBox, 0, 1);
    // Stop button:  0, 2
    m_layout->addLayout(m_colorPicksBoxLeft, 1, 0);
    m_layout->addWidget(m_canvas, 1, 1);
    m_layout->addLayout(m_colorPicksBoxRight, 1, 2);
    m_layout->addLayout(m_widthPicksBox, 2, 1);

    m_layout->addWidget(m_leftPaletteButton, 2, 0);
    m_layout->addWidget(m_rightPaletteButton, 2, 2);

    m_layout->setColumnStretch(0, 1);
    m_layout->setColumnStretch(1, 8);
    m_layout->setColumnStretch(2, 1);
    m_layout->setRowStretch(0, 1);
    m_layout->setRowStretch(1, 8);
    m_layout->setRowStretch(2, 1);
}

void KidDrawArea::setColor(QColor color)
{
    QPen pen = m_canvas->pen();
    pen.setColor(color);
    m_canvas->setPen(pen);

    // Set border on picked color pick, remove border on others
    QList<SimpleColorPick *>::const_iterator i;
    for (i = m_colorPicks->constBegin();
         i != m_colorPicks->constEnd();
         ++i) {
        if ((*i)->color() == color) {
            (*i)->setBorderWidth(PICK_BORDER_WIDTH);
        }
        else {
            (*i)->setBorderWidth(0);
        }
    }

    // Find border and background colors
    QColor borderColor, backgroundColor;
    int index = m_palette->indexOf(color.rgba());
    if (index != -1) {
        borderColor = m_borderPalette->at(index);
        backgroundColor = m_backgroundPalette->at(index);
        m_canvas->setTag(index);
    }
    else {
        m_canvas->setTag(0);
    }

    // Set colors etc. on width picks
    QList<SimpleWidthPick *>::const_iterator j;
    for (j = m_widthPicks->constBegin();
         j != m_widthPicks->constEnd();
         ++j) {
        (*j)->setColor(color);
        (*j)->setBorderColor(color);
        (*j)->setBackgroundColor(backgroundColor);
    }

    m_theme->setColorValue(color);
    m_theme->setBorderColor(borderColor);
    m_theme->setBackgroundColor(backgroundColor);
    m_leftPaletteButton->update();
    m_rightPaletteButton->update();
    m_rightPaletteButton->sizeHint();

    // Set palette arrow buttons
//     pen = m_leftPaletteButton->pen();
//     pen.setColor(borderColor);
//     QBrush brush = m_leftPaletteButton->brush();
//     brush.setColor(color);

//     m_leftPaletteButton->setPen(pen);
//     m_leftPaletteButton->setBrush(brush);
//     m_rightPaletteButton->setPen(pen);
//     m_rightPaletteButton->setBrush(brush);
}

void KidDrawArea::setLineWidth(int lineWidth)
{
    QPen pen = m_canvas->pen();
    pen.setWidth(lineWidth);
    m_canvas->setPen(pen);

    QList<SimpleWidthPick *>::const_iterator i;
    for (i = m_widthPicks->constBegin();
         i != m_widthPicks->constEnd();
         ++i) {
        if ((*i)->lineWidth() == lineWidth) {
            (*i)->setBorderWidth(PICK_BORDER_WIDTH);
        }
        else {
            (*i)->setBorderWidth(0);
        }
    }
}

void KidDrawArea::loadPalette(Palette *p)
{
    int selectedIndex = m_palette->indexOf(m_canvas->pen().color().rgba());
    delete m_palette;
    delete m_borderPalette;
    delete m_backgroundPalette;

    m_palette = new QVector<QRgb>(PaletteManager::paletteToColorTable(
            p,
            PaletteManager::value));
    m_borderPalette = new QVector<QRgb>(PaletteManager::paletteToColorTable(
            p,
            PaletteManager::border));
    m_backgroundPalette = new QVector<QRgb>(PaletteManager::paletteToColorTable(
            p,
            PaletteManager::background));

//     m_canvas->setNumColors(m_palette->size());
//     m_canvas->setColorTable(*m_palette);

    emit newPalette();

    if (selectedIndex >= 0) {
        setColor(m_palette->at(selectedIndex % m_palette->size()));
    }
}

void KidDrawArea::loadPalette(QString name)
{
    qDebug() << "Loading palette \"" << name << "\"";
    Palette *p = m_paletteManager->palettes().value(name);
    if (p != NULL) {
        loadPalette(p);
    }
}

void KidDrawArea::loadPalette(int index)
{
    Palette *p = m_paletteManager->palettes().value(
        m_paletteManager->paletteNames().at(index)
    );
    if (p != NULL) {
        loadPalette(p);
    }
}

void KidDrawArea::updatePicks()
{
    // Delete old picks
    for (QList<SimpleColorPick *>::iterator i = m_colorPicks->begin();
            i != m_colorPicks->end(); ++i) {
        SimpleColorPick *p = *i;
        m_colorPicksBoxLeft->removeWidget(p);
        m_colorPicksBoxRight->removeWidget(p);
        m_colorPicks->erase(i);
        delete (p);
    }

    // Create new picks
    int n = 0;
    SimpleColorPick *curPick;
    QVector<QRgb>::const_iterator i = m_palette->constBegin();
    QVector<QRgb>::const_iterator j = m_borderPalette->constBegin();

    for (;i != m_palette->constEnd() && j != m_borderPalette->constEnd();
         ++i, ++j, ++n) {
        // Convert color to QColor (from QRgb), then create pick
        curPick = new SimpleColorPick(QColor(*i));
        curPick->setBorderColor(QColor(*j));
        curPick->setBorderWidth(0);
        // Add pick to layout, left or right
        if (n < m_palette->size() / 2) {
            m_colorPicksBoxLeft->addWidget(curPick);
        }
        else {
            m_colorPicksBoxRight->addWidget(curPick);
        }
        // Add pick to list
        m_colorPicks->append(curPick);

        // Connect pick signal
        connect(curPick, SIGNAL(picked(QColor)),
                this, SLOT(setColor(QColor)));
    }
}

void KidDrawArea::updateCanvasColors()
{
    // Update background
    QBrush b = m_canvas->backgroundBrush();
    b.setColor(m_palette->at(0));
    m_canvas->setBackgroundBrush(b);

    // Update line colors
    QMap<qint16, QColor> colorMap;
    for (qint16 i = 0; i < m_maxTag; ++i) {
        colorMap.insert(i, QColor(m_palette->at(i % m_palette->size())));
    };
    m_canvas->adjustColors(colorMap);

    if (m_palette->size() > m_maxTag ) {
        m_maxTag = m_palette->size();
    }
}

void KidDrawArea::previousPalette()
{
    --m_paletteNumber;
    if (m_paletteNumber < 0) {
        m_paletteNumber = m_paletteManager->countPalettes() - 1;
    }
    loadPalette(m_paletteNumber);
}

void KidDrawArea::nextPalette()
{
    ++m_paletteNumber;
    if (m_paletteNumber >= m_paletteManager->countPalettes()) {
        m_paletteNumber = 0;
    }
    loadPalette(m_paletteNumber);
}

void KidDrawArea::mousePressEvent(QMouseEvent *event)
{
    // Move to right position in canvas, then set pet down
    m_canvas->moveTo(event->pos() - QPoint(m_canvas->x(), m_canvas->y()));
    m_canvas->penDown();
}

void KidDrawArea::mouseReleaseEvent(QMouseEvent * /*event*/)
{
    m_canvas->penUp();
}

void KidDrawArea::mouseMoveEvent(QMouseEvent *event)
{
    m_canvas->moveTo(event->pos() - QPoint(m_canvas->x(), m_canvas->y()));
}

bool KidDrawArea::save()
{
    KUrl url = KFileDialog::getSaveUrl(KUrl(), QString(), this, "Save KidDrawing");
    if (!url.isEmpty()) {
        qDebug() << "Got filename " << url;
        return save(url);
    }
    return false;
}

bool KidDrawArea::save(KUrl url)
{
    DrawingWriter writer;
    writer.setBackgroundImage(m_canvas->backgroundImage());
    writer.setBackgroundStyle(m_canvas->backgroundStyle());
    QString paletteName = m_paletteManager->paletteNames().at(m_paletteNumber);
    Palette palette     = *(m_paletteManager->palettes().value(paletteName));
    writer.setPalette(palette, paletteName);
    writer.setLines(m_canvas->lines());

    qDebug() << "Assigned stuff, saving";

    return writer.save(url);
}

bool KidDrawArea::load()
{
    KUrl url = KFileDialog::getOpenUrl(KUrl(), QString(), this, "Open KidDrawing");
    if (!url.isEmpty()) {
        qDebug() << "Got filename " << url;
        return load(url);
    }
    return false;
}

bool KidDrawArea::load(KUrl url)
{
    DrawingReader reader;
    QPen pen = m_canvas->pen();
    pen.setJoinStyle(Qt::MiterJoin);
    reader.setPenTemplate(pen);
    reader.load(url);

    if (reader.isValid()) {
        m_canvas->clear();
        // Background
        m_canvas->setBackgroundStyle(reader.backgroundStyle());
        m_canvas->setBackgroundImage(reader.backgroundImage());

        // Palette - create copy, check if existing, otherwise add new and load
        Palette *palette = new Palette(reader.palette());
        int pIndex = m_paletteManager->paletteNames().indexOf(reader.paletteName());
        if (pIndex >= 0) {
            qDebug() << "Found palette";
            Palette *lPalette =  m_paletteManager->palettes().value(reader.paletteName());
            if ((*lPalette) != (*palette)) {
                QString name = reader.paletteName();
                int i = 1;
                QList<QString> names = m_paletteManager->paletteNames();
                while (names.indexOf(name + " (" + QString::number(i) + ')') >= 0) {
                    ++i;
                }
                name += " (" + QString::number(i) + ')';
                m_paletteManager->addPalette(name, palette);
                pIndex = m_paletteManager->countPalettes() - 1;
            }
        }
        else {
            m_paletteManager->addPalette(reader.paletteName(), palette);
            pIndex = m_paletteManager->countPalettes() - 1;
        }
        m_paletteNumber = pIndex;
        this->loadPalette(pIndex);

        // Lines
        m_canvas->setLines(reader.lines());
        qDebug() << "Loaded!";
        return true;
    }
    qDebug() << "Error loading!";
    return false;
}

#include "kiddrawarea.moc"
