/***************************************************************************
 *   Copyright (C) 2004, 2007 by Kraschinski Arnold                        *
 *   arnold.kra67 AT gmx DOT de                                            *
 *                                                                         *
 *   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) any later version.                                   *
 *                                                                         *
 *   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, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
 ***************************************************************************/
#include "jigsaw.h"

// Standard C++ header files
#include <algorithm>
#include <stdlib.h>
#include <ctime>

// Qt header files
#include <QPainter>
#include <QSvgRenderer>
#include <QImage>
#include <QPixmap>
#include <QVector>
#include <QScrollArea>

// KDE header files
#include <kglobal.h>
#include <klocale.h>
#include <kstandarddirs.h>
#include <kmessagebox.h>



const int Jigsaw::MAXPARTS_HORIZONTICAL = MAXPARTS_H;
const int Jigsaw::MAXPARTS_VERTICAL = MAXPARTS_V;


Jigsaw::Jigsaw( QWidget* parent, QString image, int hParts, int vParts, QScrollArea* scrollArea )
: QLabel(parent), m_changed(true), m_pending(0), m_scrollArea(scrollArea)
{
    m_renderer = new QSvgRenderer(KStandardDirs::locate("appdata", "images/jigsaw.svg"));
    load ( image, hParts, vParts );
}


Jigsaw::~Jigsaw()
{
}

void Jigsaw::load( QString image, int hParts, int vParts ) {
    m_hParts = hParts;
    m_vParts = vParts;
    if ((m_hParts > MAXPARTS_HORIZONTICAL) || (m_vParts > MAXPARTS_VERTICAL)) {
        m_hParts = MAXPARTS_HORIZONTICAL;
        m_vParts = MAXPARTS_VERTICAL;
    }
    m_image = new QImage ( image );
    if ( m_image->isNull() ) {
        m_image->load( KStandardDirs::locate("appdata", "images/pferde.jpg") );
        if ( m_image->isNull() ) {
            KMessageBox::sorry( 0, i18n("Could not find any jigsaw picture.") );
        }
    }
    coverAll ();
    if (m_pending > 0) {
        slotUncover(0);
    }
    m_changed = true;
    setPixmap ( jigsaw() );
    update();
}

void Jigsaw::coverAll()
{
    for ( int i = 0; i < MAXPARTS_HORIZONTICAL; i++ )
        for ( int j = 0; j < MAXPARTS_VERTICAL; j++ )
            m_visible [i] [j] = false;
    m_changed = true;
}

bool Jigsaw::uncover()
{
    QVector<int> horizontal;
    QVector<int> vertical;
    // Search all invisible parts and store the coordinates in the vectors.
    for (int i = 0; i < m_hParts; i++) {
        for (int j = 0; j < m_vParts; j++) {
            if ( m_visible[i][j] == false ) {
                horizontal << i;
                vertical << j;
            }
        }
    }
    if ( !horizontal.isEmpty() ) {
        int count(0);
        if ( horizontal.size() > 1 ) {
            count = rand() % horizontal.size();
        } else {
            count = 0;
        }
        m_visible[horizontal[count]] [vertical[count]] = true;
        m_changed = true;
        update();
        if ( horizontal.size() == 1) {
            emit signalJigsawSolved();
        }
        return true;
    } else {
        return false;
    }
}

QPixmap Jigsaw::jigsaw ()
{
    QImage image ( *m_image );
    QPainter painter (&image);
    painter.setRenderHint( QPainter::Antialiasing );
    
    double dx = (double)image.width() / (double)m_hParts;
    double dy = (double)image.height() / (double)m_vParts;
    double sx = 1.000 / (double)m_hParts;
    double sy = 1.000 / (double)m_vParts;
    
    for (int i = 0; i < m_hParts; i ++) {
        for (int j = 0; j < m_vParts; j ++) {
            if ( !m_visible [i] [j] ) {
                painter.translate( dx * i, dy * j );
                painter.scale( sx, sy );
                if ( (i + j) % 2 == 0 ) {
                    m_renderer->render(&painter, "red_square");
                } else {
                    m_renderer->render(&painter, "square");
                }
                painter.resetMatrix();
            }
        }
    }
    
    m_changed = false;
    if (m_scale) {
        return QPixmap::fromImage( image.scaled ( m_scrollArea->maximumViewportSize(), Qt::KeepAspectRatio));
    } else {
        return QPixmap::fromImage ( image );
    }
}

void Jigsaw::scaleImage( bool scale )
{
    m_scale = scale;
}

void Jigsaw::paintEvent ( QPaintEvent* event )
{
    if (m_changed) {
        setPixmap ( jigsaw() );
    }
    QLabel::paintEvent( event );
}

void Jigsaw::slotUncover(int n)
{
    n += m_pending;
    m_pending = 0;
    while ( (n > 0) && ( uncover() ) ) {
        n--;
    }
    m_pending += n;
}


#include "jigsaw.moc"
