/***************************************************************************
 *   Copyright (C) 2006 by Bram Biesbrouck                                 *
 *   b@beligum.org                                                         *
 *                                                                         *
 *   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 St, Fifth Floor, Boston, MA  02110-1301  USA.             *
 ***************************************************************************/

#include <cstdio>
#include <cstdlib>
#include <iostream>

#include <qpainter.h>
#include <qcursor.h>
#include <qbitmap.h>

#include <kcursor.h>

#include <libinstrudeo/isdcommentbox.h>

#include "srkcommentbox.h"

//-----CONSTRUCTORS------
SRKCommentbox::SRKCommentbox(ISDCommentbox* isdBox, QWidget* parent, const char* name)
    : QWidget(parent, name),
      isdBox(isdBox),
      active(false),
      upperLeftHandle(new SRKResizeHandle(SRKResizeHandle::UPPER_LEFT, this)),
      upperRightHandle(new SRKResizeHandle(SRKResizeHandle::UPPER_RIGHT, this)),
      bottomLeftHandle(new SRKResizeHandle(SRKResizeHandle::BOTTOM_LEFT, this)),
      bottomRightHandle(new SRKResizeHandle(SRKResizeHandle::BOTTOM_RIGHT, this))
{
    //this enables the maskUpdate functions
    setAutoMask(true);

    move(0, 0);
}

//-----DESTRUCTOR-----
SRKCommentbox::~SRKCommentbox()
{
    /*
     * WARNING: don't delete the isdBox!!
     *          When the commentBox is constructed (inside libinstrudeo),
     *          it is parented to the videoCanvas (ISDVideoCanvas, that is).
     *          On destruction of the canvas, all children get deleted, including
     *          all commentboxes.
     */
}

//-----PUBLIC METHODS-----
void SRKCommentbox::scaleChanged()
{
    int pos[2];
    isdBox->getScaledPosition(pos);
    int size[2];
    isdBox->getScaledSize(size);

    move(pos[0], pos[1]);
    resize(size[0], size[1]);
}
void SRKCommentbox::setActive(bool active)
{
    this->active = active;
    
    //redraw, because the resize handles may have changed.
    if (autoMask())
	updateMask();
}
bool SRKCommentbox::isActive()
{
    return active;
}
ISDCommentbox* SRKCommentbox::getISDCommentbox()
{
    return isdBox;
}

//-----PROTECTED OVERLOADED METHODS-----
void SRKCommentbox::updateMask()
{
    if (isdBox != NULL) {
	/*
	 * prepare the mask: completely transparent,
	 * except for the handles.
	 */
	QBitmap mask(width(), height());
	QPainter maskPainter(&mask);

	//transparent
	maskPainter.setBrush(Qt::color0);
	maskPainter.setPen(Qt::color0);
	maskPainter.drawRect(0, 0, mask.width(), mask.height());

	//don't draw the resize handles if the commentbox isn't active
	if (active) {
	    //handles
	    maskPainter.setPen(Qt::color1);
	    maskPainter.setBrush(Qt::color1);
	    maskPainter.drawRect(upperLeftHandle->pos().x(),
				 upperLeftHandle->pos().y(),
				 upperLeftHandle->width(),
				 upperLeftHandle->height());
	    maskPainter.drawRect(upperRightHandle->pos().x(),
				 upperRightHandle->pos().y(),
				 upperRightHandle->width(),
				 upperRightHandle->height());
	    maskPainter.drawRect(bottomLeftHandle->pos().x(),
				 bottomLeftHandle->pos().y(),
				 bottomLeftHandle->width(),
				 bottomLeftHandle->height());
	    maskPainter.drawRect(bottomRightHandle->pos().x(),
				 bottomRightHandle->pos().y(),
				 bottomRightHandle->width(),
				 bottomRightHandle->height());
	}

	this->setMask(mask);
    }
}
void SRKCommentbox::resizeEvent(QResizeEvent*)
{
    if (isdBox != NULL) {
	//synchronize with the instrudeo commentbox
	isdBox->setScaledSize(width(), height());
	
	resizeHandles();
        
	//makes sure the mask is updated too
	if (autoMask())
	    updateMask();
    }
}
void SRKCommentbox::moveEvent(QMoveEvent*)
{
    if (isdBox != NULL) {
	//synchronize with the instrudeo commentbox
	isdBox->setScaledPosition(x(), y());
    }
}

//-----PROTECTED METHODS-----
void SRKCommentbox::resizeHandles()
{
    if (isdBox != NULL) {
	upperRightHandle->move(width()-upperRightHandle->width(), 0);
	bottomLeftHandle->move(0, height()-bottomLeftHandle->height());
	bottomRightHandle->move(width()-bottomRightHandle->width(), height()-bottomRightHandle->height());
    }
}

//-----PROTECTED NESTED CLASS-----
SRKCommentbox::SRKResizeHandle::SRKResizeHandle(ResizePosition p, QWidget* parent, const char* name)
    : QWidget(parent, name),
      fillColor(DEFAULT_HANDLE_FILL_COLOR),
      borderColor(DEFAULT_HANDLE_BORDER_COLOR),
      mode(p),
      dragging(false)
{
    resize(DEFAULT_HANDLE_WIDTH, DEFAULT_HANDLE_HEIGHT);
}
SRKCommentbox::SRKResizeHandle::~SRKResizeHandle()
{
}
void SRKCommentbox::SRKResizeHandle::paintEvent(QPaintEvent*)
{
    QPainter p(this);
    p.setBrush(fillColor);
    p.setPen(borderColor);
    p.drawRect(0, 0, width(), height());
}
void SRKCommentbox::SRKResizeHandle::enterEvent(QEvent*)
{
    switch (mode){
    case UPPER_LEFT :
	setCursor(KCursor::sizeFDiagCursor());
	break;
    case BOTTOM_RIGHT :
	setCursor(KCursor::sizeFDiagCursor());
	break;
    case UPPER_RIGHT :
	setCursor(KCursor::sizeBDiagCursor());
	break;
    case BOTTOM_LEFT :
	setCursor(KCursor::sizeBDiagCursor());
	break;
    }
}
void SRKCommentbox::SRKResizeHandle::leaveEvent(QEvent*)
{
    setCursor(KCursor::arrowCursor());
}
void SRKCommentbox::SRKResizeHandle::mousePressEvent(QMouseEvent* e)
{
    dragging = true;
    dragStartPos = e->globalPos();
    //backup the geometry of the commentbox
    dragPosBak = parentWidget()->pos();
    dragSizeBak = parentWidget()->size();
}
void SRKCommentbox::SRKResizeHandle::mouseMoveEvent(QMouseEvent* e)
{
    //fetch a reference to the commentbox
    QWidget* parent = parentWidget();
    QPoint sizeDiff = dragStartPos-e->globalPos();
    
    int newX = dragPosBak.x()-sizeDiff.x();
    int newY = dragPosBak.y()-sizeDiff.y();
    
    //the commentbox isn't allowed to move, only resize
    //the minimumcheck is performed because, as long as the new size is larger then then
    //minimum size, we don't want to fix the position
    if (newX>dragPosBak.x() && dragSizeBak.width()+sizeDiff.x()<=parent->minimumWidth())
	newX = parent->x();
    if (newY>dragPosBak.y() && dragSizeBak.height()+sizeDiff.y()<=parent->minimumHeight())
	newY = parent->y();
    
    if (dragging){
	switch (mode){
	case UPPER_LEFT :
	    parent->setGeometry(newX,
				newY,
				dragSizeBak.width()+sizeDiff.x(),
				dragSizeBak.height()+sizeDiff.y());
	    break;
	case BOTTOM_RIGHT :
	    parent->setGeometry(dragPosBak.x(),
				dragPosBak.y(),
				dragSizeBak.width()-sizeDiff.x(),
				dragSizeBak.height()-sizeDiff.y());
	    break;
	case UPPER_RIGHT :
	    parent->setGeometry(dragPosBak.x(),
				newY,
				dragSizeBak.width()-sizeDiff.x(),
				dragSizeBak.height()+sizeDiff.y());
	    break;
	case BOTTOM_LEFT :
	    parent->setGeometry(newX,
				dragPosBak.y(),
				dragSizeBak.width()+sizeDiff.x(),
				dragSizeBak.height()-sizeDiff.y());
	    break;
	}
    }
}
void SRKCommentbox::SRKResizeHandle::mouseReleaseEvent(QMouseEvent*)
{
    dragging = false;
}
