#include <boost/multi_array.hpp>
#include <GL/gl.h>
#include <QtGui/QMouseEvent>
#include "selectRectWidget.hh"

using namespace boost;
using namespace mimas;

SelectRectWidget::SelectRectWidget( QWidget *parent, Qt::WFlags f ):
  VideoWidget( parent, f ), dragging(false), haveRect(false)
{
}

void SelectRectWidget::setImage( const image< rgba< unsigned char > > &_img )
{
  dragging = false;
  haveRect = false;
  VideoWidget::setImage( _img );
  emit rectDefined( isRectDefined() );
  update();
}

void SelectRectWidget::paintGL(void)
{
  VideoWidget::paintGL();
  if ( haveRect ) {
    qglColor(Qt::red);
    // glColor4f(1,0,0,0.5);
    glPushMatrix();
    glScalef( zoom, zoom, 1.0 );
    glBegin(GL_LINE_LOOP);
    glVertex2f( x0, y0 );
    glVertex2f( x1, y0 );
    glVertex2f( x1, y1 );
    glVertex2f( x0, y1 );
    glEnd();
    glPopMatrix();
  }
}

void SelectRectWidget::mousePressEvent( QMouseEvent *e )
{
  // if left mouse-button was pressed:
  if ( e->button() == Qt::LeftButton ) {
    x0 = (int)floor( e->x() / zoom );
    y0 = (int)floor( e->y() / zoom );
    x1 = x0;
    y1 = y0;
    dragging = true;
    haveRect = true;
    update();
    emit rectDefined( isRectDefined() );
  };
}

void SelectRectWidget::mouseReleaseEvent( QMouseEvent *e )
{
  if ( e->button() == Qt::LeftButton ) {
    x1 = (int)ceil( e->x() / zoom );
    y1 = (int)ceil( e->y() / zoom );
    if ( x0 > x1 ) {
      x0 ^= x1;
      x1 ^= x0;
      x0 ^= x1;
    };
    if ( y0 > y1 ) {
      y0 ^= y1;
      y1 ^= y0;
      y0 ^= y1;
    }
    dragging = false;
    update();
    emit rectDefined( isRectDefined() );
  }
}

void SelectRectWidget::mouseMoveEvent( QMouseEvent *e )
{
  if ( dragging ) {
    x1 = (int)ceil( e->x() / zoom );
    y1 = (int)ceil( e->y() / zoom );
    update();
  };
}

void SelectRectWidget::clearSelection(void)
{
  haveRect = false;
  emit rectDefined( isRectDefined() );
}

multi_array< rgba< unsigned char >, 2 >::array_view< 2 >::type
   view( multi_array_ref< rgba< unsigned char >, 2 > &in,
         int x, int y, int w, int h )
{
  typedef multi_array< rgba< unsigned char >, 2 >::index_range range;
  typedef multi_array< rgba< unsigned char >, 2 >::array_view< 2 >::type
    array_view;
  multi_array< rgba< unsigned char >, 2 >::index_gen indices;
  array_view out = 
    in[ indices[ range( y, y + h ) ][ range( x, x + w ) ] ];
  return out;
}

image< rgba< unsigned char > > SelectRectWidget::selectedImage()
{
  image< rgba< unsigned char > > retVal;
  if ( isRectDefined() ) {
    int
      w = x1 + 1 - x0,
      h = y1 + 1 - y0;
    retVal.init( w, h );
    multi_array_ref< rgba< unsigned char >, 2 > imgData
      ( img.rawData(), extents[ img.getHeight() ][ img.getWidth() ] );
    multi_array_ref< rgba< unsigned char >, 2 >
      ( retVal.rawData(),
        extents[ retVal.getHeight() ][ retVal.getWidth() ] ) =
      view( imgData, x0, y0, w, h );
  };
  return retVal;
}