#include "armyiconlayer.h"

#include "PictureMarkerSymbol.h"
#include "Point.h"
#include "TextSymbol.h"
#include "GraphicsOverlay.h"
#include "MapGraphicsView.h"
#include "CoordinateFormatter.h"
#include "SimpleLineSymbol.h"
#include "PolylineBuilder.h"

#include <QDebug>
#include <QTextCodec>
#include <QtMath>
#include <QDir>
#include <QRandomGenerator>


using namespace Esri;
using namespace Esri::ArcGISRuntime;

ArmyIconLayer::ArmyIconLayer(QObject* parent)
    : Esri::ArcGISRuntime::GraphicsOverlay(parent)
    , mMapView(nullptr)
{
    mFocusTimer.setInterval(1000);
    connect(&mFocusTimer, &QTimer::timeout, this, &ArmyIconLayer::focusEntity);
}

ArmyIconLayer::~ArmyIconLayer()
{
}

void ArmyIconLayer::setData(const QString &data)
{
    QStringList dataList = data.split(";");
    if(!dataList.size())
        return;
    QString commond = dataList.at(0);
    //"all_entity;1,FighterAircraft,战斗机1,2400_23.5141_120.31_0;2,boat,小船1,3000_23.3452_119.828_0"
    if(commond == "all_entity")
    {
        QList<Entity> entityList;
        for(int i = 1; i < dataList.size(); i++)
        {
            Entity entity;
            QString str = dataList.at(i);
            QStringList strList = str.split(",");
            if(strList.size() >= 4)
            {
                entity.id = strList.at(0);
                entity.type = strList.at(1);
                entity.name = strList.at(2);
                entity.department = strList.at(4);
                for(int j = 4; j < strList.size(); j++)
                {
                    QString strCoor = strList.at(j);
                    QStringList strCoorList = strCoor.split("_");
                    if(strCoorList.size() >= 7)
                    {
                        CPoint p;

                        p.time = strCoorList.at(0).toInt();
                        p.longitude = strCoorList.at(1).toFloat();
                        p.latitude = strCoorList.at(2).toFloat();
                        p.altitude = strCoorList.at(3).toFloat();
                        p.pitch = strCoorList.at(4).toFloat();
                        p.yaw = strCoorList.at(5).toFloat();
                        p.roll = strCoorList.at(6).toFloat();

                        entity.route.insert(j - 4, p);
                    }

                }
            }

            entityList.append(entity);
        }

        setEntityList(entityList);
    }
    else if(commond == "all_lla")
    {
        QList<MoveEntity> list;
        //all_lla;1,23.4586,116.452,16.6667;2,22.6399,116.879,0
        for(int i = 1; i < dataList.size(); i++)
        {
            QString str = dataList.at(i);
            QStringList strList = str.split(",");
            if(strList.size() >= 7)
            {
                MoveEntity moveEntity;
                moveEntity.id = strList.at(0);
                moveEntity.latitude = strList.at(1).toFloat();
                moveEntity.longitude = strList.at(2).toFloat();
                moveEntity.altitude = strList.at(3).toFloat();
                moveEntity.pitch = strList.at(4).toFloat();
                moveEntity.yaw = strList.at(5).toFloat();
                moveEntity.roll = strList.at(6).toFloat();
                list.append(moveEntity);
            }
        }
        moveEntityList(list);
    }
}

void ArmyIconLayer::setMapView(MapGraphicsView *view)
{
    mMapView = view;
    //mMapView->graphicsOverlays()->append(this);

    connect(mMapView, &MapGraphicsView::mousePressed, this, [this](QMouseEvent& mouseEvent)
            {
                // call identify on the map view
                constexpr double tolerance = 10.0;
                constexpr bool returnPopupsOnly = false;
                constexpr int maximumResults = 1;
                // 这句代码不调用，无法触发identifyGraphicsOverlayCompleted信号
                // Esri::ArcGISRuntime::GraphicsOverlay* graphicsOverlay = this;
                TaskWatcher tw = mMapView->identifyGraphicsOverlay(this,
                                                               mouseEvent.x(),
                                                               mouseEvent.y(),
                                                               tolerance,
                                                               returnPopupsOnly,
                                                               maximumResults);
            });

    connect(mMapView, &MapGraphicsView::identifyGraphicsOverlayCompleted, this, [this](QUuid taskId, Esri::ArcGISRuntime::IdentifyGraphicsOverlayResult *identifyResult)
            {
                QList<Graphic*> graphics = identifyResult->graphics();
                int count = graphics.size();
                // qDebug() << "count:" << count;
                m_selectedGraphic = nullptr;
                if(count)
                {
                    Graphic* graphic = graphics.at(0);
                    // if(graphic->symbol()->property("id") == "line")
                    //   return;
                    //Esri::ArcGISRuntime::Symbol * symbol = graphic->symbol();
                    graphic->setSelected(!graphic->isSelected());

                    m_selectedGraphic = graphic;

                    if(m_selectedGraphic->isSelected())
                    {
                        QString id = graphic->attributes()->attributeValue("ID").toString();
                        QString name = graphic->attributes()->attributeValue("Name").toString();
                        PictureMarkerSymbol* iconSymbol = qobject_cast<PictureMarkerSymbol*>(graphic->symbol());
                        if(iconSymbol)
                            emit selectedEntity(id, name, iconSymbol->image());
                    }
                }


            });
}

void ArmyIconLayer::setEntityList(QList<Entity> list)
{
    mEntityList.clear();
    mEntityList = list;
    this->graphics()->clear();
    for(int i = 0; i < list.size(); i++)
    {
        Entity entity = mEntityList.at(i);
        QColor symbolColor;
        int colorIndex = 0;
        if(entity.department == "red")
        {
            symbolColor = Qt::red;
            colorIndex = 0;
        }
        else
        {
            symbolColor = Qt::blue;
            colorIndex = 1;
        }

        CPoint p1 = entity.route.first();
        QImage image;
        // 生成一个随机整数
        int randomNumber = QRandomGenerator::global()->generate();
        if(entity.type.toLower() == "boat")
        {
            int _idx = std::abs(randomNumber % 5);
            QString pixPath = QString(":/images/ship_obstacle/%2_ship0%1.png").arg(_idx + 1).arg(colorIndex == 0 ? "red" : "blue");
            image.load(pixPath);
        }
        else
        {
            int _idx = std::abs(randomNumber % 39);
            QString pixPath = QString(":/images/military_icon/%1.png").arg(_idx + 1);
            image.load(pixPath);
        }

        PictureMarkerSymbol* iconSymbol = new PictureMarkerSymbol(image);
        Point point(p1.longitude, p1.latitude, p1.altitude, SpatialReference::wgs84());
        TextSymbol* txtSymbol = new TextSymbol(entity.name, symbolColor, 15,
                                               HorizontalAlignment::Left, VerticalAlignment::Middle, this);
        //txtSymbol->setColor(QColor(16, 51, 240));
        txtSymbol->setOffsetX(-20);
        txtSymbol->setOffsetY(30);
        iconSymbol->setAngle(0);
        iconSymbol->setWidth(50);
        iconSymbol->setHeight(50);

        SimpleLineSymbol* lineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Dash, symbolColor,2, this);
        lineSymbol->setMarkerStyle(SimpleLineSymbolMarkerStyle::Arrow);
        PolylineBuilder polyline(SpatialReference::wgs84());
        for(int j = 0; j < entity.route.size(); j++)
        {
            CPoint p2 = entity.route[j];
            polyline.addPoint(p2.longitude, p2.latitude, p2.altitude);
        }

        QVariantMap attr;
        attr["ID"] = entity.id;
        attr["Type"] = entity.type;
        attr["Name"] = entity.name;
        attr["DisplayType"] = "Icon";
        Graphic* iconGraphic = new Graphic(point, attr, iconSymbol);
        attr["DisplayType"] = "Text";
        Graphic* textGraphic = new Graphic(point, attr, txtSymbol);
        attr["DisplayType"] = "Line";
        Graphic* lineGraphic = new Graphic(polyline.toGeometry(), attr, lineSymbol, this);
        this->graphics()->append(iconGraphic);
        this->graphics()->append(textGraphic);
        this->graphics()->append(lineGraphic);

        lineGraphic->setZIndex(1);
        textGraphic->setZIndex(2);
        iconGraphic->setZIndex(3);
        //qDebug() << coor << entity.id << entity.type << entity.name;
    }
}

void ArmyIconLayer::moveEntityList(QList<MoveEntity> list)
{
    GraphicListModel* graphicList = this->graphics();
    for(int i = 0; i < list.size(); i++)
    {
        MoveEntity moveEntity = list.at(i);
        for(int j = 0; j < graphicList->size(); j++)
        {
            Graphic* graphic = graphicList->at(j);
            QString id = graphic->attributes()->attributeValue("ID").toString();
            QString displayType = graphic->attributes()->attributeValue("DisplayType").toString();
            if(displayType == "Line")
                continue;

            if(id == moveEntity.id)
            {
                Point point(moveEntity.longitude, moveEntity.latitude, moveEntity.altitude, SpatialReference::wgs84());
                if(displayType == "Icon")
                {
                    MarkerSymbol* symbol = dynamic_cast<MarkerSymbol*>(graphic->symbol());
                    if(symbol)
                    {
//                        QGeoCoordinate coor2;
//                        coor2.setLatitude(moveEntity.latitude);
//                        coor2.setLongitude(moveEntity.longitude);
//                        QGeoCoordinate coor1;
//                        Point point1 = graphic->geometry();
//                        coor1.setLongitude(point1.x());
//                        coor1.setLatitude(point1.y());
//                        symbol->setAngle(rotateAngle(coor1, coor2));
                        double radian = moveEntity.pitch * M_PI / 180.0;
                        symbol->setAngle(radian);
                    }
                }
                graphic->setGeometry(point);

            }
        }
    }
}

void ArmyIconLayer::setEntityVisible(const QString &id, bool visible)
{
    GraphicListModel* graphicList = this->graphics();
    int count = graphicList->size();
    for(int i = 0; i < count; i++)
    {
        Graphic* graphic = graphicList->at(i);
        QString entityId = graphic->attributes()->attributeValue("ID").toString();
        QString displayType = graphic->attributes()->attributeValue("DisplayType").toString();
        if(entityId == id && (displayType == "Icon" || displayType == "Line"))
        {
            graphic->setVisible(visible);
        }
    }
}

void ArmyIconLayer::setEntityLocation(const QString &id)
{
    GraphicListModel* graphicList = this->graphics();
    int count = graphicList->size();
    for(int i = 0; i < count; i++)
    {
        Graphic* graphic = graphicList->at(i);
        QString entityId = graphic->attributes()->attributeValue("ID").toString();
        QString displayType = graphic->attributes()->attributeValue("DisplayType").toString();
        if(entityId == id && displayType == "Icon")
        {
            //mMapView->setViewpointGeometry(graphic->geometry());
            Point p = graphic->geometry();
            mMapView->setViewpointCenter(p);
        }
    }
}

void ArmyIconLayer::setEntityRouteVisible(const QString &id)
{
    GraphicListModel* graphicList = this->graphics();
    int count = graphicList->size();
    for(int i = 0; i < count; i++)
    {
        Graphic* graphic = graphicList->at(i);
        QString entityId = graphic->attributes()->attributeValue("ID").toString();
        QString displayType = graphic->attributes()->attributeValue("DisplayType").toString();
        if(entityId == id && displayType == "Line")
        {
            graphic->setVisible(!graphic->isVisible());
        }
    }
}

void ArmyIconLayer::setEntityNameVisible(const QString &id)
{
    GraphicListModel* graphicList = this->graphics();
    int count = graphicList->size();
    for(int i = 0; i < count; i++)
    {
        Graphic* graphic = graphicList->at(i);
        QString entityId = graphic->attributes()->attributeValue("ID").toString();
        QString displayType = graphic->attributes()->attributeValue("DisplayType").toString();
        if(entityId == id && displayType == "Text")
        {
            graphic->setVisible(!graphic->isVisible());
        }
    }
}

void ArmyIconLayer::setEntityFocusing(const QString &id)
{
    mFocusID = id;
    if(mFocusTimer.isActive())
        mFocusTimer.stop();
    else
        mFocusTimer.start();
}

void ArmyIconLayer::focusEntity()
{
    GraphicListModel* graphicList = this->graphics();
    int count = graphicList->size();
    for(int i = 0; i < count; i++)
    {
        Graphic* graphic = graphicList->at(i);
        QString entityId = graphic->attributes()->attributeValue("ID").toString();
        QString displayType = graphic->attributes()->attributeValue("DisplayType").toString();
        if(entityId == mFocusID && displayType == "Icon")
        {
            Point p = graphic->geometry();
            mMapView->setViewpointCenter(p);
        }
    }
}

float ArmyIconLayer::rotateAngle(QGeoCoordinate position1, QGeoCoordinate position2)
{

    qreal angleRadian = qAtan((position2.longitude() - position1.longitude()) /
                              (position2.latitude() - position1.latitude()));
    qreal angleDegree = 0;


    // 卡迪尔坐标系第一象限或第四象限
    if((position2.longitude() > position1.longitude() && position2.latitude() > position1.latitude()) ||
        (position2.longitude() < position1.longitude() && position2.latitude() > position1.latitude()))
    {
        // 弧度转角度
        angleDegree = qRadiansToDegrees(angleRadian);
    }
    else
    {
        angleDegree = qRadiansToDegrees(angleRadian) + 180;
    }

    return angleDegree;

}
