#include "changemask.h"
#include "ui_changemask.h"
#include <QPainter>
#include <QPolygon>
#include <QMouseEvent>
#include <QToolButton>

// Erstellt den Dialog
//  m: Die Maske, welche editiert werden soll
//  cam: Die Kamera, zu welcher die Maske gehört
//  parent: Der Eltern QWidget von Qt
ChangeMask::ChangeMask( Mask *m, Kamera *cam, QWidget *parent ) :
    QDialog(parent),
    ui(new Ui::ChangeMask),
    cam( cam )
{
    ui->setupUi(this);
    setWindowTitle( "Maske von " + cam->getName() );
    Frame *f = cam->getFrame( 0 );
    m->loadMask();
    if( m->getMask()->isNull() )
        m->createMask( f->getImage().size() );
    view = new ChangeMaskView( f->getImage(), m->getMask(), ui->widget );
}

ChangeMask::~ChangeMask()
{
    delete ui;
    delete view;
}

// Setzt die Farbe zukünftiger Polygone auf schwarz
void ChangeMask::on_black_clicked()
{
    ui->black->setChecked( true );
    ui->white->setChecked( false );
    view->setBlack( true );
}

// Setzt die Farbe zukünftiger Polygone auf Weiß
void ChangeMask::on_white_clicked()
{
    ui->white->setChecked( true );
    ui->black->setChecked( false );
    view->setBlack( false );
}

// Bricht das Ändern der Maske ab ohne sie zu speichern
void ChangeMask::on_abort_clicked()
{
    this->close();
}

// Beendet das Ändern der Maske und speichert sie
void ChangeMask::on_save_clicked()
{
    this->close();
    cam->saveMask();
}

// Inhalt der ChangeMaskView Klasse
//----------------------------------
// Erstellt die Ansicht
//  background: Ein Bild der Kamera, zu der die Maske editiert werden soll
//  mask: Das Schwarz-Weiß Bild, welches die momentane Maske darstellt
//  parent: Der Eltern QWidget von Qt
ChangeMaskView::ChangeMaskView(QImage background, QImage *mask,QWidget *parent)
    : QWidget( parent ),
      background( background ),
      mask( mask ),
      xScaleFactor( 1 ),
      yScaleFactor( 1 ),
      black( true )
{
    parent->layout()->addWidget( this );
    this->setMouseTracking( true );
}

ChangeMaskView::~ChangeMaskView()
{}

// Wandelt einen Punkt aus Bildkoordinaten in Bildschirmkoordinaten um
QPoint ChangeMaskView::translate( QPoint p )
{
    return QPoint( (int)(p.x() * xScaleFactor + 20), (int)(p.y() * yScaleFactor + 20) );
}

// Wandelt einen Punkt aus Bildschirmkoordinaten in Bildkoordinaten um
QPoint ChangeMaskView::inverseTranslate( QPoint p )
{
    return QPoint( (int)((p.x()-20) / xScaleFactor), (int)((p.y()-20) / yScaleFactor) );
}

// Setzt die Zeichenfarbe
//  black: Falls 0 wird in Zukunft mit weiß gezeichnet, andernfalls mit
// schwarz
void ChangeMaskView::setBlack( bool black )
{
    this->black = black;
}

// Zeichnet die Ansicht (wird automatisch vom Qt Framework aufgerufen)
void ChangeMaskView::paintEvent(QPaintEvent *e)
{
    QSize s = size() - QSize( 40, 40 );
    QRect imgRect( QPoint( 20, 20 ), s );
    QSize imgS = background.size();
    if( imgS.width() > s.width() )
    {
        imgS.scale( s, Qt::KeepAspectRatio );
        imgRect.setSize( imgS );
    }
    // Aktualisiere die Skallierungs Faktoren
    xScaleFactor = imgRect.width() / (float)background.width();
    yScaleFactor = imgRect.height() / (float)background.height();
    QPainter painter( this );
    // Zeichne Hintergrundbild un Maske
    painter.drawImage( QRect( translate( QPoint( 0, 0 ) ), translate( QPoint( background.width(), background.height() ) ) ), background );
    painter.setOpacity( 0.75 );
    painter.drawImage( QRect( translate( QPoint( 0, 0 ) ), translate( QPoint( mask->width(), mask->height() ) ) ), *mask );
    painter.setOpacity( 1 );
    painter.setPen( QPen( QColor( 0, 255, 0 ), 2, Qt::DotLine ) );
    if( polygon.size() == 0 )
        painter.drawEllipse( (int)(mousePos.x()) - 2, (int)(mousePos.y()) - 2, 5, 5 );
    else
    { // Zeichne das aktuelle Polygon
        for( auto p = polygon.begin(); p != polygon.end() - 1; p++ )
            painter.drawLine( translate( *p ), translate( *(p + 1) ) );
        if( inverseTranslate( mousePos ).x() > polygon.begin()->x() - 30 && inverseTranslate( mousePos ).x() < polygon.begin()->x() + 30 &&
            inverseTranslate( mousePos ).y() > polygon.begin()->y() - 30 && inverseTranslate( mousePos ).y() < polygon.begin()->y() + 30 )
        {
            painter.drawLine( translate( *polygon.begin() ), translate( *(polygon.end() - 1) ) );
        }
        else
        {
            painter.drawLine( translate( *polygon.begin() ), mousePos );
            painter.drawLine( mousePos, translate( *(polygon.end() - 1) ) );
            painter.drawEllipse( (int)(mousePos.x()) - 2, (int)(mousePos.y()) - 2, 5, 5 );
        }
    }
}

// Verarbeitet Maus Bewegungen (wird automatisch vom Qt Framework
// aufgerufen)
void ChangeMaskView::mouseMoveEvent( QMouseEvent *e )
{
    mousePos = e->pos();
    repaint();
}

// Verarbeitet Maus Tastendrücke (wird automatisch vom Qt Framework
// aufgerufen)
void ChangeMaskView::mouseReleaseEvent( QMouseEvent *e )
{
    QPoint pos = inverseTranslate( e->pos() );
    if( pos.x() > polygon.begin()->x() - 30 && pos.x() < polygon.begin()->x() + 30 &&
        pos.y() > polygon.begin()->y() - 30 && pos.y() < polygon.begin()->y() + 30 )
    {
        QPainter painter;
        painter.begin( mask );
        if( black )
        {
            painter.setBrush( QBrush( QColor( 0, 0, 0 ), Qt::SolidPattern ) );
            painter.setPen( QPen( QColor( 0, 0, 0 ) ) );
        }
        else
        {
            painter.setBrush( QBrush( QColor( 255, 255, 255), Qt::SolidPattern ) );
            painter.setPen( QPen( QColor( 255, 255, 255 ) ) );
        }
        painter.drawPolygon( polygon );
        polygon.clear();
    }
    else
        polygon.append( pos );
    repaint();
}
