#include <QPen>
#include <QPainter>
#include "mainwindow.h"
#include "mygraphicsscene.h"
#include "mygraphicsview.h"

MyGraphicsScene::MyGraphicsScene(QObject *parent) :
        QGraphicsScene(parent)
{
    input = 0;
    color_line = Qt::black;
    color_polygon_fill = Qt::white;
    color_polygon_line = Qt::black;
    color_circle_line = Qt::black;
    color_circle_fill = Qt::white;
    penwidth_line = 3;
    penwidth_polygon = 3;
    penwidth_circle = 3;
    style_polygon_fill = Qt::SolidPattern;    
    set_diameter = false;
    diameter = 10;
    draw_fill = false;
    selected_state = false;
    typeof_selectitem = 0;

    if (draw_fill == true)
        style_circle_fill = Qt::SolidPattern;
    else
        style_circle_fill = Qt::NoBrush;

    circle_construction_method = 1;
}

void MyGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{

    if (event->button() == Qt::LeftButton)
    {

        switch(input)
        {
        case 1: // kresleni kruznice
            {
                apoint = event->scenePos();

                if (set_diameter == false)
                {

                    switch(circle_construction_method)
                    {
                    case 1: //kresleni stredu a bodu na obvode
                        {

                            if (center_circle.isNull())
                                center_circle = apoint;
                            else
                            {
                                double radius = getPointDistance(center_circle, apoint);
                                diameter = 2*radius;

                                QPen pen;
                                pen.setColor(color_circle_line);
                                pen.setWidth(penwidth_circle);

                                QBrush brush;
                                brush.setColor(color_circle_fill);
                                if (draw_fill)
                                    brush.setStyle(Qt::SolidPattern);

                                this->addEllipse(center_circle.x()-radius, center_circle.y()-radius, diameter, diameter, pen, brush);

                                center_circle = QPointF();
                            }
                            break;
                        }

                    case 2: //kresleni prumeru
                        {
                            if (point1.isNull())
                                point1 = apoint;
                            else
                            {
                                center_circle = getMidPoint(point1, apoint);
                                diameter = getPointDistance(point1, apoint);
                                double radius = diameter/2;

                                QPen pen;
                                pen.setColor(color_circle_line);
                                pen.setWidth(penwidth_circle);

                                QBrush brush;
                                brush.setColor(color_circle_fill);
                                if (draw_fill)
                                    brush.setStyle(Qt::SolidPattern);

                                this->addEllipse(center_circle.x()-radius, center_circle.y()-radius, diameter, diameter, pen, brush);

                                center_circle = QPointF();
                                point1 = QPointF();
                            }

                            break;
                        }

                    case 3: //kresleni 3 bodu na obvode
                        {
                            if (point1.isNull())
                                point1 = apoint;
                            else
                            {
                                if (point2.isNull())
                                {
                                    point2 = apoint;
                                }
                                else
                                {
                                    center_circle = getCenterFrom3Points(point1, point2, apoint);
                                    double radius = getPointDistance(center_circle, apoint);
                                    diameter = 2*radius;

                                    QPen pen;
                                    pen.setColor(color_circle_line);
                                    pen.setWidth(penwidth_circle);

                                    QBrush brush;
                                    brush.setColor(color_circle_fill);
                                    if (draw_fill)
                                        brush.setStyle(Qt::SolidPattern);

                                    this->addEllipse(center_circle.x()-radius, center_circle.y()-radius, diameter, diameter, pen, brush);

                                    center_circle = QPointF();
                                    point1 = QPointF();
                                    point2 = QPointF();
                                }
                            }

                            break;
                        }
                    }
                }
                else
                {
                    QPen pen;
                    pen.setColor(color_circle_line);
                    pen.setWidth(penwidth_circle);

                    QBrush brush;
                    brush.setColor(color_circle_fill);

                    if (draw_fill)
                        brush.setStyle(Qt::SolidPattern);

                    double radius = diameter/2;
                    this->addEllipse(apoint.x()-radius,apoint.y()-radius,diameter,diameter, pen, brush);
                }



                break;
            }
        case 2: // kresleni polyline
            {
                if (lastpoint.isNull()) //prvnibod
                {
                    apolyline.addPoint(event->scenePos());
                    lastpoint = event->scenePos();

                    QPen pen;
                    pen.setColor(color_line);
                    pen.setWidth(penwidth_line);
                    pen.setStyle(Qt::DashLine);

                    this->addPolyline(apolyline, pen);
                }
                else //dalsi body bez posledniho
                {
                    QList<QGraphicsItem *> list = this->items();
                    QList<QGraphicsItem *>::iterator item = list.begin();

                    if (*item)
                    {
                        removeItem(*item);
                    }

                    apolyline.addPoint(event->scenePos());
                    lastpoint = event->scenePos();

                    QPen pen;
                    pen.setColor(color_line);
                    pen.setWidth(penwidth_line);
                    pen.setStyle(Qt::DashLine);

                    this->addPolyline(apolyline, pen);
                }
                break;
            }
        case 3: //kresleni polygonu
            {
                if (lastpoint.isNull())
                {
                    apolygon << event->scenePos();
                    lastpoint = event->scenePos();

                    QPen pen;
                    pen.setColor(color_polygon_line);
                    pen.setWidth(penwidth_polygon);
                    pen.setStyle(Qt::DashLine);

                    QBrush brush;
                    brush.setColor(color_polygon_fill);
                    brush.setStyle(Qt::DiagCrossPattern);

                    this->addPolygon(apolygon, pen, brush);
                }
                else
                {                                     
                    QList<QGraphicsItem *> list = this->items();
                    QList<QGraphicsItem *>::iterator item = list.begin();

                    if (*item)
                    {
                        removeItem(*item);
                    }


                    apolygon << event->scenePos();
                    lastpoint = event->scenePos();

                    QPen pen;
                    pen.setColor(color_polygon_line);
                    pen.setWidth(penwidth_polygon);
                    pen.setStyle(Qt::DashLine);

                    QBrush brush;
                    brush.setColor(color_polygon_fill);
                    brush.setStyle(Qt::DiagCrossPattern);

                    this->addPolygon(apolygon, pen, brush);
                }
                break;
            }
        case 0:
            {   if (selected_state == true)
                {
                    switch (typeof_selectitem)
                    {
                    case 1:
                        {
                            selected_polygon->setBrush(polygon_origbrush);
                            selected_polygon->setPen(polygon_origpen);
                            break;
                        }
                    case 2:
                        {
                            selected_polyline->setPen(polyline_origpen);
                            break;
                        }
                    case 3:
                        {
                            selected_circle->setBrush(circle_origbrush);
                            selected_circle->setPen(circle_origpen);
                            break;
                        }
                    }


                }

                if (selected_item = itemAt(event->scenePos()))
                {
                    selected_state = true;

                    int typ =  selected_item->type();

                    switch (typ)
                    {
                    case 0:
                        break;
                    case QGraphicsPolygonItem::Type:
                        {
                            selected_polygon = (QGraphicsPolygonItem*) selected_item;
                            polygon_origbrush = selected_polygon->brush();
                            polygon_origpen = selected_polygon->pen();
                            QBrush selectedpolygonbrush = QBrush();
                            selectedpolygonbrush.setColor(polygon_origbrush.color());
                            selectedpolygonbrush.setStyle(Qt::Dense3Pattern);
                            QPen selectedpolygonpen = QPen();
                            selectedpolygonpen.setColor(polygon_origpen.color());
                            selectedpolygonpen.setWidth(polygon_origpen.width());
                            selectedpolygonpen.setStyle(Qt::DotLine);
                            selected_polygon->setBrush(selectedpolygonbrush);
                            selected_polygon->setPen(selectedpolygonpen);

                            update();

                            typeof_selectitem = 1;
                            break;
                        }
                    case MyGraphicsPolylineItem::Type:
                        {
                            selected_polyline = (MyGraphicsPolylineItem*) selected_item;
                            polyline_origpen = selected_polyline->getPen();
                            QPen selectedpolylinepen = QPen();
                            selectedpolylinepen.setColor(polyline_origpen.color());
                            selectedpolylinepen.setWidth(polyline_origpen.width());
                            selectedpolylinepen.setStyle(Qt::DotLine);
                            selected_polyline->setPen(selectedpolylinepen);

                            update();

                            typeof_selectitem = 2;
                            break;
                        }
                    case QGraphicsEllipseItem::Type:
                        {
                            selected_circle = (QGraphicsEllipseItem*) selected_item;
                            circle_origbrush = selected_circle->brush();
                            circle_origpen = selected_circle->pen();
                            QBrush selectedcirclebrush = QBrush();
                            selectedcirclebrush.setColor(circle_origbrush.color());
                            selectedcirclebrush.setStyle(Qt::Dense3Pattern);
                            QPen selectedcirclepen = QPen();
                            selectedcirclepen.setColor(circle_origpen.color());
                            selectedcirclepen.setWidth(circle_origpen.width());
                            selectedcirclepen.setStyle(Qt::DotLine);
                            selected_circle->setBrush(selectedcirclebrush);
                            selected_circle->setPen(selectedcirclepen);

                            update();

                            typeof_selectitem = 3;
                            break;
                        }
                    default:
                        break;
                    }
                }
                else
                {
                    //selected_polygon->setBrush(polygon_origbrush);
                    selected_state = false;
                    typeof_selectitem = 0;
                    update();
                }


                break;
            }
        default:
            {
                break;
            }
        }
    }
    else if (event->button() == Qt::RightButton)
    {               
        if(input == 2)
        {
            if (!lastpoint.isNull()) // posledni bod polylinie
            {
                apolyline.addPoint(event->scenePos());

                QList<QGraphicsItem *> list = this->items();
                QList<QGraphicsItem *>::iterator item = list.begin();

                if (*item)
                {
                    removeItem(*item);
                }

                QPen pen;
                pen.setColor(color_line);
                pen.setWidth(penwidth_line);

                this->addPolyline(apolyline, pen);

                apolyline.clear();

                lastpoint = QPointF(); // nulovani lastpoint
            }
        }
        else if(input == 3) // polygon
        {
            if (!lastpoint.isNull())
            {
                apolygon << event->scenePos();

                QList<QGraphicsItem *> list = this->items();
                QList<QGraphicsItem *>::iterator item = list.begin();

                if (*item)
                {
                    removeItem(*item);
                }

                QPen pen;
                pen.setColor(color_polygon_line);
                pen.setWidth(penwidth_polygon);

                QBrush brush;
                brush.setColor(color_polygon_fill);
                brush.setStyle(Qt::SolidPattern);

                this->addPolygon(apolygon, pen, brush);

                apolygon.clear();
                lastpoint = QPointF(); // nulovani lastpoint
            }

        }

    }

    //ui->sourX->setText(QString::number(event->pos()));
    //ui->sourY->setText(QString::number(event->pos()));

}

void MyGraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{

}


void MyGraphicsScene::closePolygon()      // ukonci polygon - vola se pri predcasnem kliknuti na kreslici buttony
{
    QList<QGraphicsItem *> list = this->items();
    QList<QGraphicsItem *>::iterator item = list.begin();

    if (*item)
    {
        removeItem(*item);
    }

    QPen pen;
    pen.setColor(color_polygon_line);
    pen.setWidth(penwidth_polygon);

    QBrush brush;
    brush.setColor(color_polygon_fill);
    brush.setStyle(Qt::SolidPattern);

    this->addPolygon(apolygon, pen, brush);

    apolygon.clear();
    lastpoint = QPointF(); // nulovani lastpoint
}

void MyGraphicsScene::closePolyline()
{
    QList<QGraphicsItem *> list = this->items();
    QList<QGraphicsItem *>::iterator item = list.begin();

    if (*item)
    {
        removeItem(*item);
    }

    QPen pen;
    pen.setColor(color_line);
    pen.setWidth(penwidth_line);

    this->addPolyline(apolyline, pen);

    apolyline.clear();
    lastpoint = QPointF(); // nulovani lastpoint
}

MyGraphicsPolylineItem *MyGraphicsScene::addPolyline(MyGraphicsPolylineItem &polyline, const QPen &pen)
{
    MyGraphicsPolylineItem *item = new MyGraphicsPolylineItem(polyline);
    item->setPen(pen);
    addItem(item);
    return item;
}

double MyGraphicsScene::getPointDistance(QPointF &p1, QPointF &p2)
{
    return sqrt(((p1.x()-p2.x())*(p1.x()-p2.x())) + ((p1.y()-p2.y())*(p1.y()-p2.y())));
}

QPointF MyGraphicsScene::getMidPoint(QPointF &p1, QPointF &p2)
{
    return QPointF(((p1.x()+p2.x())/2), ((p1.y()+p2.y())/2));
}

QPointF MyGraphicsScene::getCenterFrom3Points(QPointF &p1, QPointF &p2, QPointF &p3)
{
    QLineF line1hlp = QLineF(getMidPoint(p1, p2),p1);
    QLineF line1 = line1hlp.normalVector();

    QLineF line2hlp = QLineF(getMidPoint(p3, p2), p3);
    QLineF line2 = line2hlp.normalVector();

    QPointF intersect;

    line1.intersect(line2, &intersect);

    return intersect;
}

void MyGraphicsScene::setDrawFill(bool draw_fill_)
{
    this->draw_fill = draw_fill_;

    if (draw_fill == true)
        style_circle_fill = Qt::SolidPattern;
    else
        style_circle_fill = Qt::NoBrush;
}

void MyGraphicsScene::setDiameter(double diameter_)
{
    this->diameter = diameter_;
}

bool MyGraphicsScene::circleIsComplete()
{
    if (this->center_circle.isNull() && this->point1.isNull() && this->point2.isNull())
        return true;
    return false;
}

void MyGraphicsScene::cancelCircle()
{
    center_circle = QPointF();
    point1 = QPointF();
    point2 = QPointF();
}

void MyGraphicsScene::saveChanges(QBrush brush_polygon, QPen pen_polygon, QPen pen_polyline, QPen pen_circle, QBrush brush_circle)
{
    selected_state = false;
    typeof_selectitem = 0;
    int typ =  selected_item->type();

    switch (typ)
    {
    case 0:
        break;
    case QGraphicsPolygonItem::Type:
        {
            selected_polygon = (QGraphicsPolygonItem*) selected_item;

            selected_polygon->setBrush(brush_polygon);
            selected_polygon->setPen(pen_polygon);
            update();
            selected_polygon = NULL;

            break;
        }
    case MyGraphicsPolylineItem::Type:
        {
            selected_polyline = (MyGraphicsPolylineItem*) selected_item;

            selected_polyline->setPen(pen_polyline);
            update();
            selected_polyline = NULL;
            break;
        }
    case QGraphicsEllipseItem::Type:
        {
            selected_circle = (QGraphicsEllipseItem*) selected_item;

            selected_circle->setPen(pen_circle);
            selected_circle->setBrush(brush_circle);
            update();
            selected_circle = NULL;
            break;
        }
    default:
        break;
    }
    //}



}



















