#include "fullscreen.h"
#include <qapplication.h>
#include <qcursor.h>
#include <qpainter.h>
#include <qlayout.h>
#include <qtooltip.h>
#include <qdrawutil.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kglobal.h>
#include <kconfig.h>
#include <kimageeffect.h>

#include <stdlib.h>

KIFFullScreenHandle::KIFFullScreenHandle(QWidget *parent, const char *name)
    : QButton(parent, name)
{
    setToggleButton(true);
    setOn(true);
}

QSize KIFFullScreenHandle::sizeHint() const
{
    return(QSize(12, 12));
}


void KIFFullScreenHandle::drawButton(QPainter *p)
{
    p->fillRect(0, 0, width(), height(),
                colorGroup().background());
    qDrawShadePanel(p, 0, 0, width(), height(), colorGroup(), isDown());
    qDrawArrow(p, isOn() || isDown() ? Qt::LeftArrow : Qt::RightArrow,
               Qt::WindowsStyle, isDown(), 2, 2, width()-4, height()-4,
               colorGroup(), true);
}


KIFFullScreen::KIFFullScreen(KIFImage *image, bool maxpect, QWidget *parent,
                             const char *name, bool dirBtnEnabled)
    : QWidget(parent, name, WType_Popup)
{
    KConfig *config = KGlobal::config();
    config->setGroup("UISettings");

    setFocusPolicy(StrongFocus);
    setBackgroundMode(NoBackground);

    gc = XCreateGC(x11Display(), RootWindow(x11Display(), x11Screen()), 0, 0);

    // alloc color for lowcolor displays
    c = config->readColorEntry("FullScreenColor", &Qt::white);
    XSetForeground(x11Display(), gc, c.pixel());

    imageBuffer = image;
    max = maxpect;
    connect(imageBuffer, SIGNAL(updated()), this, SLOT(slotUpdateFromImage()));
    connect(imageBuffer, SIGNAL(invalidFile()), this, SLOT(slotInvalidFile()));
    move(0, 0);
    resize(QApplication::desktop()->size());

    QGridLayout *layout = new QGridLayout(this);
    handle = new KIFFullScreenHandle(this);
    connect(handle, SIGNAL(toggled(bool)), this,
            SLOT(slotHandleToggled(bool)));
    layout->addWidget(handle, 0, 0);

    if(dirBtnEnabled){
        prevImageBtn = new QToolButton(this);
        QToolTip::add(prevImageBtn, i18n("Previous image in folder"));
        prevImageBtn->setIconSet(BarIcon("backimage", 16));
        connect(prevImageBtn, SIGNAL(clicked()), this, SLOT(slotPrevImageClicked()));
        layout->addWidget(prevImageBtn, 0, 1);
        nextImageBtn = new QToolButton(this);
        QToolTip::add(nextImageBtn, i18n("Next image in folder"));
        nextImageBtn->setIconSet(BarIcon("forwardimage", 16));
        connect(nextImageBtn, SIGNAL(clicked()), this, SLOT(slotNextImageClicked()));
        layout->addWidget(nextImageBtn, 0, 2);
    }
    else{
        prevImageBtn = nextImageBtn = NULL;
    }
    prevListBtn = new QToolButton(this);
    QToolTip::add(prevListBtn, i18n("Previous image in file list"));
    prevListBtn->setIconSet(BarIcon("1leftarrow", 16));
    connect(prevListBtn, SIGNAL(clicked()), this, SLOT(slotPrevListClicked()));
    layout->addWidget(prevListBtn, 0, 3);
    nextListBtn = new QToolButton(this);
    QToolTip::add(nextListBtn, i18n("Next image in file list"));
    nextListBtn->setIconSet(BarIcon("1rightarrow", 16));
    connect(nextListBtn, SIGNAL(clicked()), this, SLOT(slotNextListClicked()));
    layout->addWidget(nextListBtn, 0, 4);

    handle->setMinimumHeight(prevListBtn->sizeHint().height());

    incBrightnessBtn = new QToolButton(this);
    QToolTip::add(incBrightnessBtn, i18n("Increase brightness"));
    incBrightnessBtn->setIconSet(BarIcon("brightness", 16));
    connect(incBrightnessBtn, SIGNAL(clicked()), this,
            SLOT(slotIncBrightnessClicked()));
    layout->addWidget(incBrightnessBtn, 0, 5);

    decBrightnessBtn = new QToolButton(this);
    QToolTip::add(decBrightnessBtn, i18n("Decrease brightness"));
    decBrightnessBtn->setIconSet(BarIcon("dim", 16));
    connect(decBrightnessBtn, SIGNAL(clicked()), this,
            SLOT(slotDecBrightnessClicked()));
    layout->addWidget(decBrightnessBtn, 0, 6);

    incContrastBtn = new QToolButton(this);
    QToolTip::add(incContrastBtn, i18n("Increase contrast"));
    incContrastBtn->setIconSet(BarIcon("contrast+", 16));
    connect(incContrastBtn, SIGNAL(clicked()), this,
            SLOT(slotIncContrastClicked()));
    layout->addWidget(incContrastBtn, 0, 7);

    decContrastBtn = new QToolButton(this);
    QToolTip::add(decContrastBtn, i18n("Decrease contrast"));
    decContrastBtn->setIconSet(BarIcon("contrast-", 16));
    connect(decContrastBtn, SIGNAL(clicked()), this,
            SLOT(slotDecContrastClicked()));
    layout->addWidget(decContrastBtn, 0, 8);

    rotateBtn = new QToolButton(this);
    QToolTip::add(rotateBtn, i18n("Rotate"));
    rotateBtn->setIconSet(BarIcon("rotate", 16));
    connect(rotateBtn, SIGNAL(clicked()), this,
            SLOT(slotRotateClicked()));
    layout->addWidget(rotateBtn, 0, 9);

    zoomBtn = new QToolButton(this);
    QToolTip::add(zoomBtn, i18n("Zoom in/out"));
    zoomBtn->setIconSet(BarIcon("viewmag", 16));
    connect(zoomBtn, SIGNAL(clicked()), this,
            SLOT(slotZoomClicked()));
    layout->addWidget(zoomBtn, 0, 10);

    layout->setColStretch(11, 1);
    layout->setRowStretch(1, 1);

    if(!config->readBoolEntry("ViewerToolbar", true))
        handle->toggle();

    maxBtnClicked = false;
}

KIFFullScreen::~KIFFullScreen()
{
    XFreeGC(x11Display(), gc);
}

void KIFFullScreen::setColor(const QColor &color)
{
    c = color;
    XSetForeground(x11Display(), gc, c.pixel());
}

void KIFFullScreen::slotHandleToggled(bool on)
{
    if(on){
        if(prevImageBtn){
            prevImageBtn->show();
            nextImageBtn->show();
        }
        prevListBtn->show();
        nextListBtn->show();
        incBrightnessBtn->show();
        decBrightnessBtn->show();
        incContrastBtn->show();
        decContrastBtn->show();
        rotateBtn->show();
        zoomBtn->show();
    }
    else{
        if(prevImageBtn){
            prevImageBtn->hide();
            nextImageBtn->hide();
        }
        prevListBtn->hide();
        nextListBtn->hide();
        incBrightnessBtn->hide();
        decBrightnessBtn->hide();
        incContrastBtn->hide();
        decContrastBtn->hide();
        rotateBtn->hide();
        zoomBtn->hide();
    }
    KConfig *config = KGlobal::config();
    config->setGroup("UISettings");
    config->writeEntry("ViewerToolbar", on);
    config->sync();
    update();
}

void KIFFullScreen::slotIncContrastClicked()
{
    QApplication::setOverrideCursor(WaitCursor);
    QImage tmpImage = pix.convertToImage();
    KImageEffect::contrastHSV(tmpImage, true);
    pix.convertFromImage(tmpImage);
    repaint(false);
    QApplication::restoreOverrideCursor();
}

void KIFFullScreen::slotDecContrastClicked()
{
    QApplication::setOverrideCursor(WaitCursor);
    QImage tmpImage = pix.convertToImage();
    KImageEffect::contrastHSV(tmpImage, false);
    pix.convertFromImage(tmpImage);
    repaint(false);
    QApplication::restoreOverrideCursor();
}

void KIFFullScreen::slotIncBrightnessClicked()
{
    int i, count, h, s, v;
    unsigned int *data;
    QColor pixel;

    QApplication::setOverrideCursor(WaitCursor);
    QImage tmpImage = pix.convertToImage();
    if(tmpImage.depth() < 32)
        tmpImage = tmpImage.convertDepth(32);

    count = tmpImage.width()*tmpImage.height();
    data = (unsigned int *)tmpImage.bits();
    for(i=0; i < count; ++i){
        pixel.setRgb(qRed(data[i]), qGreen(data[i]), qBlue(data[i]));
        pixel.hsv(&h, &s, &v);
        if(v+10 <= 255)
            v+=10;
        else
            v = 255;
        pixel.setHsv(h, s, v);
        data[i] = qRgb(pixel.red(), pixel.green(), pixel.blue());
    }
    pix.convertFromImage(tmpImage);
    repaint(false);
    QApplication::restoreOverrideCursor();
}

void KIFFullScreen::slotDecBrightnessClicked()
{
    int i, count, h, s, v;
    unsigned int *data;
    QColor pixel;

    QApplication::setOverrideCursor(WaitCursor);
    QImage tmpImage = pix.convertToImage();
    if(tmpImage.depth() < 32)
        tmpImage = tmpImage.convertDepth(32);

    count = tmpImage.width()*tmpImage.height();
    data = (unsigned int *)tmpImage.bits();
    for(i=0; i < count; ++i){
        pixel.setRgb(qRed(data[i]), qGreen(data[i]), qBlue(data[i]));
        pixel.hsv(&h, &s, &v);
        if(v-10 > 0)
            v-=10;
        else
            v = 0;
        pixel.setHsv(h, s, v);
        data[i] = qRgb(pixel.red(), pixel.green(), pixel.blue());
    }
    pix.convertFromImage(tmpImage);
    repaint(false);
    QApplication::restoreOverrideCursor();
}

void KIFFullScreen::slotRotateClicked()
{
    QApplication::setOverrideCursor(WaitCursor);
    QImage tmpImage = pix.convertToImage();
    tmpImage = KImageEffect::rotate(tmpImage, KImageEffect::Rotate90);
    scale(tmpImage);
    pix.convertFromImage(tmpImage);
    repaint(false);
    QApplication::restoreOverrideCursor();
}

void KIFFullScreen::slotZoomClicked()
{
    QApplication::setOverrideCursor(WaitCursor);
    if(pix.width() == width() || pix.height() == height()){
        if(pix.width() > width() || pix.height() > height()){
            QImage tmpImage = pix.convertToImage();
            int w = tmpImage.width();
            int h = tmpImage.height();
            if(w > width()){
                float percent = ((float)width())/w;
                w = (int)(w*percent);
                h = (int)(h*percent);
            }
            if(h > height()){
                float percent = ((float)height())/h;
                w = (int)(w*percent);
                h = (int)(h*percent);
            }
            tmpImage = tmpImage.smoothScale(w, h);
            pix.convertFromImage(tmpImage);
        }
        else
            pix.convertFromImage(*imageBuffer->image());
    }
    else{
        QImage tmpImage(*imageBuffer->image());
        int w = tmpImage.width();
        int h = tmpImage.height();
        float percentW, percentH;

        percentW = percentH = 0.0;
        if(tmpImage.width() < width())
            percentW = ((float)width())/w;
        if(tmpImage.height() < height())
            percentH = ((float)height())/h;
        if(percentW && ((int)(h * percentW)) <= height()){
            w = (int)(w*percentW);
            h = (int)(h*percentW);
        }
        else if(percentH && ((int)(w * percentH)) <= width()){
            w = (int)(w*percentH);
            h = (int)(h*percentH);
        }
        tmpImage = tmpImage.smoothScale(w, h);
        pix.convertFromImage(tmpImage);
    }
    repaint(false);
    QApplication::restoreOverrideCursor();
}

void KIFFullScreen::slotUpdateFromImage()
{
    if(imageBuffer->image()->width() > width() ||
       imageBuffer->image()->height() > height()){
        QImage tmpImage(*imageBuffer->image());
        scale(tmpImage);
        pix.convertFromImage(tmpImage);
    }
    else if(max && imageBuffer->image()->width() < width() &&
            imageBuffer->image()->height() < height()){
        QImage tmpImage(*imageBuffer->image());
        scale(tmpImage);
        pix.convertFromImage(tmpImage);
    }
    else
        pix.convertFromImage(*imageBuffer->image());
    repaint(false);
}

void KIFFullScreen::slotInvalidFile()
{
    ;
}

void KIFFullScreen::scale(QImage &tmpImage)
{
    if(tmpImage.width() > width() || tmpImage.height() > height()){
        int w = tmpImage.width();
        int h = tmpImage.height();
        if(w > width()){
            float percent = ((float)width())/w;
            w = (int)(w*percent);
            h = (int)(h*percent);
        }
        if(h > height()){
            float percent = ((float)height())/h;
            w = (int)(w*percent);
            h = (int)(h*percent);
        }
        tmpImage = tmpImage.smoothScale(w, h);
    }
    else if(max && tmpImage.width() < width() && tmpImage.height() < height()){
        int w = tmpImage.width();
        int h = tmpImage.height();
        float percentW, percentH;
        // decide if to scale horizontally or vertically
        percentW = percentH = 0.0;
        if(tmpImage.width() < width())
            percentW = ((float)width())/w;
        if(tmpImage.height() < height())
            percentH = ((float)height())/h;
        // can we scale width to screensize w/out making height offscreen
        if(percentW && ((int)(h * percentW)) <= height()){
            w = (int)(w*percentW);
            h = (int)(h*percentW);
        }
        // if not try to scale horizontally w/out making width offscreen
        else if(percentH && ((int)(w * percentH)) <= width()){
            w = (int)(w*percentH);
            h = (int)(h*percentH);
        }
        tmpImage = tmpImage.smoothScale(w, h);
    }
}


void KIFFullScreen::paintEvent(QPaintEvent *ev)
{
    if(pix.isNull()){
        XFillRectangle(x11Display(), winId(), gc, 0, 0, width(), height());
        return;
    }
    QRect pixRect(0, 0, pix.width(), pix.height());
    QRect drawRect(ev->rect());
    if(pix.width() < width()){
        pixRect.setLeft(((width()-pix.width())/2)-1);
        pixRect.setWidth(pix.width()); // need to reset
    }
    if(pix.height() < height()){
        pixRect.setTop(((height()-pix.height())/2)-1);
        pixRect.setHeight(pix.height());
    }
    pixRect = pixRect.intersect(drawRect);
    if(pix.mask())
        XFillRectangle(x11Display(), winId(), gc, pixRect.x(),
                       pixRect.y(), drawRect.width(), drawRect.height());
    bitBlt(this, pixRect.topLeft(), &pix, drawRect, Qt::CopyROP);
    // fill in the edges
    int rects = 0;
    XRectangle rectangles[4];
    if(drawRect.top() < pixRect.top()){
        rectangles[rects].x = drawRect.x();
        rectangles[rects].y = drawRect.x();
        rectangles[rects].width = drawRect.width();
        rectangles[rects].height =  pixRect.top()-drawRect.top();
        ++rects;
    }
    if(drawRect.left() < pixRect.left()){
        rectangles[rects].x = drawRect.x();
        rectangles[rects].y = pixRect.top()-drawRect.top();
        rectangles[rects].width = pixRect.left()-drawRect.left();
        rectangles[rects].height = drawRect.height()-pixRect.top();
        ++rects;
    }
    if(drawRect.right() > pixRect.right()){
        rectangles[rects].x = pixRect.right()+1;
        rectangles[rects].y = pixRect.top()-drawRect.top();
        rectangles[rects].width = drawRect.right()-pixRect.right();
        rectangles[rects].height = drawRect.height()-pixRect.top();
        ++rects;
    }
    if(drawRect.bottom() > pixRect.bottom()){
        rectangles[rects].x = pixRect.left();
        rectangles[rects].y = pixRect.bottom()+1;
        rectangles[rects].width = pixRect.width();
        rectangles[rects].height = drawRect.bottom()-pixRect.bottom();
        ++rects;
    }
    if(rects)
        XFillRectangles(x11Display(), winId(), gc, rectangles, rects);
}

void KIFFullScreen::closeEvent(QCloseEvent *ev)
{
    pix.resize(0, 0);
    ev->accept();
    emit finished();
}

void KIFFullScreen::mousePressEvent(QMouseEvent *ev)
{
    if(ev->button() == LeftButton){
        close();
    }
}

void KIFFullScreen::slotNextListClicked()
{
    emit(nextList());
}

void KIFFullScreen::slotPrevListClicked()
{
    emit(prevList());
}

void KIFFullScreen::slotNextImageClicked()
{
    emit(nextImage());
}

void KIFFullScreen::slotPrevImageClicked()
{
    emit(prevImage());
}

void KIFFullScreen::keyPressEvent(QKeyEvent *ev)
{
    int key = ev->key();
    if(key == Key_Left)
        emit(prevList());
    else if(key == Key_Right || key == Key_Space)
        emit(nextList());
    else if(key == Key_Up)
        emit(prevImage());
    else if(key == Key_Down)
        emit(nextImage());
    else if(key == Key_Escape || key == Key_Enter || key == Key_Return)
        close();
}




#include "fullscreen.moc"
