#include <QKeyEvent>
#include <canvasitem.h>
#include <canvas.h>

int CanvasItemFactory::id = 0;

CanvasItem::CanvasItem(Canvas *p, int _x, int _y, int _w, int _h)
{
    widget = new QLabel(p);
    customWidget = 0;
    //widget->setAttribute(Qt::WA_PaintOnScreen);
    parent = p;
    parentWidget = p;
    deleted = false;
    id = CanvasItemFactory::id++;
    x = _x;
    y = _y;
    w = _w;
    h = _h;
    fillW = -1;
    fillH = -1;
    clip = QRect(0,0,0,0);
    visible = false;
    layer = 0;

    QList<CanvasItem*>::iterator i = qUpperBound( parent->items.begin(), parent->items.end(), this, Canvas::canvasItemLessThan );
    parent->items.insert(i, this);
}

void CanvasItem::layer_set(int l)
{
    layer = l;
    parent->items.removeAll(this);
    QList<CanvasItem*>::iterator i = qUpperBound( parent->items.begin(), parent->items.end(), this, Canvas::canvasItemLessThan );
    parent->items.insert(i, this);
    if (visible)
        parent->realShowWidget(this);
}

void CanvasItem::deleted_set(bool v)
{
    deleted = v;
    if (deleted) {
        parent->removeItem(this);
	deleteLater();
    }
}

void CanvasItem::text_set(QString l)
{
	text = l;
	if (type == 2) { // TEXT
            widget->setText(text);
	    if ( !clip.isNull() ) {
		QFontMetrics fm(widget->font());
		if ( fm.width(text) > clip.width() )
            	    widget->setAlignment(Qt::AlignRight);
		else
            	    widget->setAlignment(Qt::AlignLeft);
            }
            updateGeometry();
        }
}

void CanvasItem::vis_set(bool l)
{
    if ( visible == l )
	return;
    visible = l;
    if (visible) {
        widget->show();
        parent->realShowWidget(this);
    } else {
        widget->hide();
    }
}

void CanvasItem::file_set(QString l)
{
    if (file==l)
	return;
    file = l;
    if (type == 0) { // IMAGE
	QPixmap pm;
	if (!QPixmapCache::find(file, pm)) {
	    pm.load(file);
	    QPixmapCache::insert(file, pm);
	}
	if ( fillW > 0 && fillH > 0 ) {
	    w = fillW;
	    h = fillH;
	} else {
	    w = pm.width();
	    h = pm.height();
	}
	QString f = file + "_scaled_" + w + "_" + h; 
	if (!QPixmapCache::find(f, pm)) {
	    pm.load(file);
	    pm = pm.scaled(QSize(w,h));
	    QPixmapCache::insert(f, pm);
	}
	widget->setPixmap(pm);
	//widget->setPixmap(pm.scaled(QSize(w,h)));
	updateGeometry();
    }
}

int CanvasItem::w_get()
{
    if (type == 2) { // TEXT
        QFontMetrics fm(widget->font());
	if ( !clip.isNull() ) {
	    if ( fm.width(text) > clip.width() )
		return clip.width();
        }
        return fm.width(text) + 4;
    }
    return w;
}

int CanvasItem::h_get()
{
    if (type == 2) { // TEXT
        QFontMetrics fm(widget->font());
        h = fm.height();
    }
    return h;
}

void CanvasItem::color_set(QColor col)
{
    color = col;
    QPalette p;
    p.setColor(QPalette::WindowText,color);
    widget->setPalette(p);
}

int CanvasItem::descent_get()
{
    QFontMetrics fm(widget->font());
    return fm.descent();
}

void CanvasItem::resize(int _w, int _h)
{
    if (type == 1) { // RECT
	w_set(_w);
	h_set(_h);
    } 
    if (type != 0) // Only image can resize
	return;
    QPixmap pm;
    if (!QPixmapCache::find(file, pm)) {
        pm.load(file);
        QPixmapCache::insert(file, pm);
    }
    w = _w;
    h = _h;
    //widget->setPixmap(pm.copy(0, 0, _w, _h));
    //printf("resize: %i %i\n", w, h);
    updateGeometry();
    //widget->resize(w,h);
	    
    QString f = file + "_scaled_" + _w + "_" + _h; 
    if (!QPixmapCache::find(f, pm)) {
        pm.load(file);
	pm = pm.scaled(QSize(_w,_h));
        QPixmapCache::insert(f, pm);
    }
    widget->setPixmap(pm);
}

void CanvasItem::fill_set(int , int , int width, int height)
{
    if (type != 0)
	return;
    fillW = width;
    fillH = height;
    resize(width, height);
}

/* convert the key strings used in the python code to the equivelent Qt key codes */
static int QtKeyCodeFromString(QString key)
{
    int qt_key = 0;
    if ( key == "F1" )
	qt_key = Qt::Key_Context1;
    else if ( key == "F2" )
	qt_key = Qt::Key_Context2;
    else if ( key == "SOFT3" )
	qt_key = Qt::Key_Context3;
    else if ( key == "SOFT4" )
	qt_key = Qt::Key_Context4;
    else {
    	char ch = key.toLatin1().data()[0];
	switch (ch) {
	    case 'O': qt_key = Qt::Key_Enter;      break; // OK 
	    case 'L': qt_key = Qt::Key_Left;       break; // Left
	    case 'R': qt_key = Qt::Key_Right;      break; // Right
	    case 'U': qt_key = Qt::Key_Up;         break; // Up
	    case 'D': qt_key = Qt::Key_Down;       break; // Down
	    case '*': qt_key = Qt::Key_Asterisk;   break; // '*'
	    case '#': qt_key = Qt::Key_NumberSign; break; // '#'
	    case '1': qt_key = Qt::Key_1;          break; // '1'
            case '2': qt_key = Qt::Key_2;          break; // '2'
	    case '3': qt_key = Qt::Key_3;          break; // '3'
	    case '4': qt_key = Qt::Key_4;          break; // '4'
	    case '5': qt_key = Qt::Key_5;          break; // '5'
	    case '6': qt_key = Qt::Key_6;          break; // '6'
	    case '7': qt_key = Qt::Key_7;          break; // '7'
	    case '8': qt_key = Qt::Key_8;          break; // '8'
	    case '9': qt_key = Qt::Key_9;          break; // '9'
	    case '0': qt_key = Qt::Key_0;          break; // '0'
	    default:
		printf("Edit  qtpyui/server/" __FILE__ " %i to add mapping "
			"for unhandled key %s\n", __LINE__, key.toLatin1().data());
		break;
        }
    }
    return qt_key;
}

/*
  Workaround to call the keyEvent protected functions so we can inject
  keys in standard way to the custom item and so the custom item can
  inherit QWidget and be programmed in the regular way to handle keys.
*/
class CustomWidget : public QWidget
{
public:
	virtual void keyPressEvent(QKeyEvent *ke);
	virtual void keyReleaseEvent(QKeyEvent *ke);
};

/* dispatch key events to any custom widget */
bool CanvasItem::handleKey(QString key, bool down)
{
    if ( customWidget ) {
	QKeyEvent ke((down) ? QEvent::KeyPress : QEvent::KeyRelease, QtKeyCodeFromString(key), Qt::NoModifier);
	if ( down )
	    ((CustomWidget*)customWidget)->keyPressEvent(&ke);
	else	
	    ((CustomWidget*)customWidget)->keyReleaseEvent(&ke);
	return true;
    }
    return false;
}


