/** *************************************************************************
                          fovsymbolnode.cpp  -  K Desktop Planetarium
                             -------------------
    begin                : 20/08/2016
    copyright            : (C) 2016 by Artem Fedoskin
    email                : afedoskin3@gmail.com
 ***************************************************************************/
/** *************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
#include "fovsymbolnode.h"

#include "nodes/rectnode.h"
#include "nodes/ellipsenode.h"

#include <QSGFlatColorMaterial>

FOVSymbolNode::FOVSymbolNode(const QString &name, float a, float b, float xoffset, float yoffset, float rot, FOVItem::Shape shape, const QString &color)
    :m_symbol(nullptr)
{
    m_name = name;
    m_sizeX = a;
    m_sizeY = (b < 0.0) ? a : b;

    m_offsetX     = xoffset;
    m_offsetY     = yoffset;
    m_rotation    = rot;
    m_color       = color;
    m_northPA     = 0;
    m_center.setRA(0);
    m_center.setDec(0);

    switch(shape)
    {
    case FOVItem::SQUARE:
        m_symbol = new SquareFOV();
        break;
    case FOVItem::CIRCLE:
        m_symbol = new CircleFOV();
        break;
    case FOVItem::CROSSHAIRS:
        m_symbol = new CrosshairFOV();
        break;
    case FOVItem::BULLSEYE:
        m_symbol = new BullsEyeFOV();
        break;
    case FOVItem::SOLIDCIRCLE:
        m_symbol = new SolidCircleFOV();
        break;
    default:
        break;
    }

    if(m_symbol) addChildNode(m_symbol);
}

void FOVSymbolNode::update(float zoomFactor) {
    show();
    float pixelSizeX = m_sizeX * zoomFactor / 57.3 / 60.0;
    float pixelSizeY = m_sizeY * zoomFactor / 57.3 / 60.0;

    float offsetXPixelSize = m_offsetX * zoomFactor / 57.3 / 60.0;
    float offsetYPixelSize = m_offsetY * zoomFactor / 57.3 / 60.0;
    SkyMapLite *map = SkyMapLite::Instance();

    QMatrix4x4 newMatrix;

    if (m_center.ra().Degrees() > 0)
    {
        m_center.EquatorialToHorizontal(KStarsData::Instance()->lst(), KStarsData::Instance()->geo()->lat());
        QPointF skypoint_center = map->projector()->toScreen(&m_center);
        newMatrix.translate(skypoint_center.toPoint().x(), skypoint_center.toPoint().y());
    } else {
        QPoint center(map->width()/2, map->height()/2);
        newMatrix.translate(center.x(), center.y());
    }

    newMatrix.translate(offsetXPixelSize,  offsetYPixelSize);
    newMatrix.rotate(m_rotation+m_northPA,0, 0, 1);

    m_symbol->setMatrix(newMatrix);

    m_symbol->updateSymbol(m_color, pixelSizeX, pixelSizeY);
}

FOVSymbolBase::FOVSymbolBase(FOVItem::Shape shape)
    :m_shape(shape) //Will be changed by the subclass
{

}

SquareFOV::SquareFOV()
    :FOVSymbolBase(FOVItem::SQUARE)
{
    rect1 = new RectNode();
    appendChildNode(rect1);

    rect2 = new RectNode();
    appendChildNode(rect2);

    lines = new QSGGeometryNode;
    appendChildNode(lines);

    lines->setGeometry(new QSGGeometry (QSGGeometry::defaultAttributes_Point2D(),0));
    lines->setOpaqueMaterial(new QSGFlatColorMaterial);
    lines->setFlag(QSGNode::OwnsGeometry);
    lines->setFlag(QSGNode::OwnsMaterial);
    lines->geometry()->allocate(6);
    lines->geometry()->setDrawingMode(GL_LINES);
}

void SquareFOV::updateSymbol(QColor color, float pixelSizeX, float pixelSizeY ) {
    QPoint center(0,0);

    /*if (m_imageDisplay)
    {
        //QTransform imageT;
        //imageT.rotate(m_rotation+m_northPA);
        //p.drawImage(targetRect, m_image.transformed(imageT));
        p.drawImage(targetRect, m_image);
    }*/

    rect1->setRect(center.x() - pixelSizeX/2, center.y() - pixelSizeY/2, pixelSizeX, pixelSizeY);
    rect1->setColor(color);

    rect2->setRect(center.x() , center.y() - (3 * pixelSizeY/5), pixelSizeX/40, pixelSizeX/10);
    rect2->setColor(color);

    QSGFlatColorMaterial *material = static_cast<QSGFlatColorMaterial *>(lines->opaqueMaterial());
    if(material->color() != color) {
        material->setColor(color);
        lines->markDirty(QSGNode::DirtyMaterial);
    }

    QSGGeometry::Point2D * vertex = lines->geometry()->vertexDataAsPoint2D();
    vertex[0].set(center.x() - pixelSizeX/30, center.y() - (3 * pixelSizeY/5));
    vertex[1].set(center.x() + pixelSizeX/20, center.y() - (3 * pixelSizeY/5));

    vertex[2].set(center.x() - pixelSizeX/30, center.y() - (3 * pixelSizeY/5));
    vertex[3].set(center.x() + pixelSizeX/70, center.y() - (0.7 * pixelSizeY));

    vertex[4].set(center.x() + pixelSizeX/20, center.y() - (3 * pixelSizeY/5));
    vertex[5].set(center.x() + pixelSizeX/70, center.y() - (0.7 * pixelSizeY));

    lines->markDirty(QSGNode::DirtyGeometry);
}

CircleFOV::CircleFOV()
    :FOVSymbolBase(FOVItem::CIRCLE)
{
    el = new EllipseNode();
    appendChildNode(el);
}

void CircleFOV::updateSymbol(QColor color, float pixelSizeX, float pixelSizeY ) {
    el->setColor(color);
    el->updateGeometry(0,0, pixelSizeX/2, pixelSizeY/2,false);
}

CrosshairFOV::CrosshairFOV()
    :FOVSymbolBase(FOVItem::CROSSHAIRS)
{
    lines = new QSGGeometryNode;
    appendChildNode(lines);

    lines->setGeometry(new QSGGeometry (QSGGeometry::defaultAttributes_Point2D(),0));
    lines->setOpaqueMaterial(new QSGFlatColorMaterial);
    lines->setFlag(QSGNode::OwnsGeometry);
    lines->setFlag(QSGNode::OwnsMaterial);
    lines->geometry()->allocate(8);
    lines->geometry()->setDrawingMode(GL_LINES);

    el1 = new EllipseNode;
    appendChildNode(el1);

    el2 = new EllipseNode;
    appendChildNode(el2);
}

void CrosshairFOV::updateSymbol( QColor color, float pixelSizeX, float pixelSizeY ) {
    QPoint center(0,0);

    QSGGeometry::Point2D * vertex = lines->geometry()->vertexDataAsPoint2D();
    vertex[0].set(center.x() + 0.5*pixelSizeX, center.y());
    vertex[1].set(center.x() + 1.5*pixelSizeX, center.y());

    vertex[2].set(center.x() - 0.5*pixelSizeX, center.y());
    vertex[3].set(center.x() - 1.5*pixelSizeX, center.y());

    vertex[4].set(center.x(), center.y() + 0.5*pixelSizeY);
    vertex[5].set(center.x(), center.y() + 1.5*pixelSizeY);

    vertex[6].set(center.x(), center.y() - 0.5*pixelSizeY);
    vertex[7].set(center.x(), center.y() - 1.5*pixelSizeY);

    lines->markDirty(QSGNode::DirtyGeometry);

    //Draw circles at 0.5 & 1 degrees
    el1->setColor(color);
    el1->updateGeometry(center.x(), center.y(), 0.5 * pixelSizeX, 0.5 * pixelSizeY, false);

    el2->setColor(color);
    el1->updateGeometry(center.x(), center.y(), pixelSizeX, pixelSizeY, false);
}

BullsEyeFOV::BullsEyeFOV()
    :FOVSymbolBase(FOVItem::BULLSEYE)
{
    el1 = new EllipseNode;
    appendChildNode(el1);

    el2 = new EllipseNode;
    appendChildNode(el2);

    el3 = new EllipseNode;
    appendChildNode(el3);
}

void BullsEyeFOV::updateSymbol( QColor color, float pixelSizeX, float pixelSizeY ) {
    el1->setColor(color);
    el1->updateGeometry(0, 0, 0.5 * pixelSizeX, 0.5 * pixelSizeY, false);

    el2->setColor(color);
    el2->updateGeometry(0, 0, 2.0 * pixelSizeX, 2.0 * pixelSizeY, false);

    el3->setColor(color);
    el3->updateGeometry(0, 0, 4.0 * pixelSizeX, 4.0 * pixelSizeY, false);
}

SolidCircleFOV::SolidCircleFOV()
    :FOVSymbolBase(FOVItem::SOLIDCIRCLE)
{
    el = new EllipseNode;
    appendChildNode(el);
}

void SolidCircleFOV::updateSymbol( QColor color, float pixelSizeX, float pixelSizeY ) {
    QColor colorAlpha = color;
    colorAlpha.setAlpha(127);
    el->setColor(colorAlpha);
    el->updateGeometry( 0, 0, pixelSizeX/2, pixelSizeY/2, false );
}

