/***************************************************************************
 *   Copyright (C) 2009 by Manuel Schrape                                  *
 *   manuel.schrape@gmx.de                                                 *
 *                                                                         *
 *   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.        *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "dlg_Map.h"
#include "dlg_MapPos.h"


#include <QDomDocument>
#include <QFile>

dlg_Map::dlg_Map(QWidget *parent) : QDialog(parent)
{
    setupUi(this);

    cb_Maps->removeItem(5);
    cb_Maps->removeItem(4);
//    cb_Maps->removeItem(3);
//    cb_Maps->removeItem(2);

    pb_Add->setEnabled(false);
    pb_Goto->setEnabled(false);
}

// Karte erstellen und anzeigen
void dlg_Map::create_Map(cSettings *t_Settings)
{
    o_Settings = t_Settings;

    cb_CenterPos->setChecked(o_Settings->Map.GotoPosition);
    cb_ShowRoute->setChecked(o_Settings->Map.ShowTrack);

    connect(sl_Zoom,   SIGNAL(valueChanged(int)), this, SLOT(slot_Zoom(int)));
    connect(pb_Add,    SIGNAL(clicked()), this, SLOT(slot_AddWayPoint()));
    connect(pb_Delete, SIGNAL(clicked()), this, SLOT(slot_DeleteWayPoints()));
    connect(pb_Goto,   SIGNAL(clicked()), this, SLOT(slot_GotoTarget()));
    connect(pb_SendWaypoints, SIGNAL(clicked()), this, SLOT(slot_SendWayPoints()));
    connect(pb_LoadPic,   SIGNAL(clicked()), this, SLOT(slot_LoadMapPic()));

    connect(pb_Load,   SIGNAL(clicked()), this, SLOT(slot_LoadWayPoints()));
    connect(pb_Save,   SIGNAL(clicked()), this, SLOT(slot_SaveWayPoints()));

    connect(cb_Maps,   SIGNAL(currentIndexChanged(int)), this, SLOT(slot_ChangeMap(int)));
    connect(cb_ShowWPs, SIGNAL(toggled(bool)), this, SLOT(slot_ShowWayPoints(bool)));

    connect(this,      SIGNAL(rejected()), this, SLOT(slot_Close()));

    o_Map = new MapControl(w_Map->size());
    o_Map->enablePersistentCache(o_Settings->DIR.Cache);
    o_Map->showScale(true);

    o_Adapter = new OSMMapAdapter();

    o_Layer = new MapLayer("MapLayer", o_Adapter);
    o_Click = new GeometryLayer("Click", o_Adapter);
    o_Route = new GeometryLayer("Poute", o_Adapter);

    o_Map->addLayer(o_Layer);
    o_Map->addLayer(o_Click);
    o_Map->addLayer(o_Route);

    o_Map->setZoom(17);
//    o_Map->setView(QPointF(13.5,52.5));
    o_Map->setView(QPointF(o_Settings->Map.LastLongitude,o_Settings->Map.LastLatitude));

    connect(o_Map, SIGNAL(mouseEventCoordinate(const QMouseEvent*, const QPointF)), this, SLOT(slot_Click(const QMouseEvent*, const QPointF)));

    l_Map->addWidget(o_Map);

    sl_Zoom->setValue(17);

    Pen[0] = new QPen(QColor(0,0,255,255));
    Pen[0]->setWidth(2);
    Pen[1] = new QPen(QColor(255,0,0,255));
    Pen[1]->setWidth(2);
}

QList<sWayPoint> dlg_Map::parse_WayPointKML(QString s_File)
{
    QList<sWayPoint> tmp_WayPoints;
    sWayPoint tmp_WayPoint;

    QFile f_KML(s_File);
    f_KML.open(QIODevice::ReadOnly | QIODevice::Text);

    QByteArray s_KML;

    while (!f_KML.atEnd())
    {
        s_KML.append(f_KML.readLine());
     }

    f_KML.close();

    QDomDocument *UserXML;
    UserXML = new QDomDocument;

    UserXML->setContent(s_KML);

    QDomElement Root       = UserXML->firstChildElement("kml");
    QDomElement Document   = Root.firstChildElement("Document");
    QDomElement Placemark  = Document.firstChildElement("Placemark");
    QDomElement Linestring = Placemark.firstChildElement("LineString");

    QString Name = Placemark.firstChildElement("name").toElement().text();

    QString Route = Linestring.firstChildElement("coordinates").toElement().text();

    QStringList s_Points = Route.split(" ");

    QStringList Position;

    for (int z = 0; z < s_Points.count() - 1; z++)
    {
        if (z != 20)
        {
           Position = s_Points[z].split(",");
           tmp_WayPoint.Longitude = Position[0].toDouble();
           tmp_WayPoint.Latitude  = Position[1].toDouble();
           tmp_WayPoint.Altitude  = Position[2].toDouble();
           tmp_WayPoint.Time      = sb_Time->value();

           tmp_WayPoints.append(tmp_WayPoint);
        }
        else
        {
            QMessageBox::warning(this, QA_NAME,trUtf8("Die Wegpunkt-Liste umfasst mehr als 20 Einträge. Es werden nur die ersten 20 Einträge übernommen."), QMessageBox::Ok);

            pb_Add->setEnabled(false);

            z = s_Points.count();
        }
    }
    return tmp_WayPoints;
}

QList<sWayPoint> dlg_Map::parse_WayPointMKW(QString s_File)
{
    QList<sWayPoint> tmp_WayPoints;
    sWayPoint tmp_WayPoint;

    QFile f_MKW(s_File);
    f_MKW.open(QIODevice::ReadOnly | QIODevice::Text);

    QString s_MKW;

    while (!f_MKW.atEnd())
    {
        s_MKW.append(f_MKW.readLine());
     }

    f_MKW.close();

    QStringList s_Points = s_MKW.split(" ");

    QStringList Position;

    for (int z = 0; z < s_Points.count() - 1; z++)
    {
        if (z != 20)
        {
           Position = s_Points[z].split(",");
           tmp_WayPoint.Longitude = Position[0].toDouble();
           tmp_WayPoint.Latitude  = Position[1].toDouble();
           tmp_WayPoint.Altitude  = Position[2].toDouble();
           tmp_WayPoint.Time      = Position[3].toInt();

           tmp_WayPoints.append(tmp_WayPoint);
        }
        else
        {
            QMessageBox::warning(this, QA_NAME,trUtf8("Die Wegpunkt-Liste umfasst mehr als 20 Einträge. Es werden nur die ersten 20 Einträge übernommen."), QMessageBox::Ok);

            pb_Add->setEnabled(false);

            z = s_Points.count();
        }
    }
    return tmp_WayPoints;
}

void dlg_Map::show_WayPoints(QList<sWayPoint> WayPoints)
{
    Point* p_Point;

    o_Route->removeGeometry(l_RouteWP);
    p_RouteWP.clear();
    l_WayPoints.clear();

    l_WayPoints = WayPoints;

    for (int z = 0; z < WayPoints.count(); z++)
    {
        p_Point = new Point(WayPoints[z].Longitude, WayPoints[z].Latitude);

        p_RouteWP.append(p_Point);
    }

    l_RouteWP = new LineString(p_RouteWP, "", Pen[0]);
    o_Route->addGeometry(l_RouteWP);

    o_Map->setView(p_Point);

    o_Map->updateRequestNew();    
}

void dlg_Map::save_WayPointsMKW(QString s_File)
{
    QFile *f_MKW = new QFile(s_File);

    f_MKW->open(QIODevice::ReadWrite | QIODevice::Text);

    QTextStream out(f_MKW);

    out.setRealNumberPrecision(9);

    for (int z = 0; z < l_WayPoints.count(); z++)
    {
        out << l_WayPoints[z].Longitude << "," << l_WayPoints[z].Latitude << "," << l_WayPoints[z].Altitude << "," << l_WayPoints[z].Time << " \n";
    }

    f_MKW->close();
}

void dlg_Map::slot_LoadWayPoints()
{
    QString Filename = QFileDialog::getOpenFileName(this, "WayPoint-Route laden",  o_Settings->DIR.Logging, "Mikrokopter WayPoints(*.mkw);;KML-Datei(*.kml);;Alle Dateien (*)");

    if (!Filename.isEmpty())
    {
        if (Filename.endsWith(".kml", Qt::CaseInsensitive))
        {
            cb_ShowWPs->setChecked(true);
            pb_SendWaypoints->setEnabled(true);

            show_WayPoints(parse_WayPointKML(Filename));
        }
        if (Filename.endsWith(".mkw", Qt::CaseInsensitive))
        {
            cb_ShowWPs->setChecked(true);
            pb_SendWaypoints->setEnabled(true);

            show_WayPoints(parse_WayPointMKW(Filename));
        }
    }
}

void dlg_Map::slot_SaveWayPoints()
{
    QString Filename = QFileDialog::getSaveFileName(this, "WayPoint-Route speichern",  o_Settings->DIR.Logging, "Mikrokopter WayPoints(*.mkw);;Alle Dateien (*)");

    if (!Filename.isEmpty())
    {
        if (!(Filename.endsWith(".mkw", Qt::CaseInsensitive)))
        {
            Filename = Filename + QString(".mkw");
        }

        save_WayPointsMKW(Filename);
    }
}

void dlg_Map::slot_ShowWayPoints(bool Show)
{
    if (Show == true)
    {
        qDebug("An");
        o_Route->addGeometry(l_RouteWP);
        o_Map->updateRequestNew();
    }
    else
    {
        qDebug("Aus");
        o_Route->removeGeometry(l_RouteWP);
        o_Map->updateRequestNew();
    }
}

// Position zum Flug-Track hinzufügen
void dlg_Map::add_Position(double x, double y)
{
    sWayPoint WayPoint;

    o_Settings->Map.LastLongitude = x;
    o_Settings->Map.LastLatitude = y;

    WayPoint.Longitude = x;
    WayPoint.Latitude = y;
//    WayPoint.Time = sb_Time->value();

    l_Track.append(WayPoint);

    o_Route->removeGeometry(l_RouteFL);
    p_RouteFL.append(new Point(x,y));

    o_Click->removeGeometry(LastPos);

    Point* P = new CirclePoint(x, y, "P1", Point::Middle, Pen[0]);
    LastPos = P;
    P->setBaselevel(17);
    o_Click->addGeometry(P);

    if (cb_CenterPos->isChecked())
    {
        o_Map->setView(QPointF(x, y));
    }

    if (cb_ShowRoute->isChecked())
    {
        l_RouteFL = new LineString(p_RouteFL, "", Pen[1]);

        o_Route->addGeometry(l_RouteFL);
    }
    o_Map->updateRequestNew();
}

// Zoom der Karte ändern
void dlg_Map::slot_Zoom(int t_Zoom)
{
    o_Map->setZoom(t_Zoom);
}

// Waypoint zur Liste hinzufügen
void dlg_Map::slot_AddWayPoint()
{
    cb_ShowWPs->setChecked(true);

    sWayPoint WayPoint;

    WayPoint.Longitude = LastClick->longitude();
    WayPoint.Latitude = LastClick->latitude();
    WayPoint.Time = sb_Time->value();

    l_WayPoints.append(WayPoint);

    o_Route->removeGeometry(l_RouteWP);

    p_RouteWP.append(LastClick);
    l_RouteWP = new LineString(p_RouteWP, "", Pen[0]);

    o_Route->addGeometry(l_RouteWP);
    o_Map->updateRequestNew();

    pb_SendWaypoints->setEnabled(true);

    if (l_WayPoints.count() == 20)
    {
        QMessageBox::warning(this, QA_NAME,trUtf8("Wegpunkt-Liste ist voll. Es können maximal 20 Wegpunkte benutzt werden."), QMessageBox::Ok);
        pb_Add->setEnabled(false);
    }

}

// Waypoint-Liste löschen
void dlg_Map::slot_DeleteWayPoints()
{
    o_Route->removeGeometry(l_RouteWP);
    p_RouteWP.clear();
    l_WayPoints.clear();
    o_Map->updateRequestNew();

    pb_Add->setEnabled(pb_Goto->isEnabled());
}

void dlg_Map::slot_SendWayPoints()
{
    emit(set_WayPoints(l_WayPoints));
}

// Zum Zielpunkt fliegen
void dlg_Map::slot_GotoTarget()
{
    sWayPoint Target;

    Target.Longitude = LastClick->longitude();
    Target.Latitude = LastClick->latitude();
    Target.Time = sb_Time->value();

    emit(set_Target(Target));
}

// Click in der Karte
void dlg_Map::slot_Click(const QMouseEvent* Event, const QPointF Coord)
{
    if ((Event->type() == QEvent::MouseButtonPress) && ((Event->button() == Qt::RightButton) || (Event->button() == Qt::MidButton)))
    {
        sl_Zoom->setValue(o_Adapter->adaptedZoom());
    }

    // Überwachen ob Karte verschoben wird
    if ((Event->type() == QEvent::MouseButtonPress) && (Event->button() == Qt::LeftButton))
    {
        MapCenter = o_Map->currentCoordinate();
    }

    // Nur wenn nicht Verschoben dann einen Punkt setzen
    if ((Event->type() == QEvent::MouseButtonRelease) && (Event->button() == Qt::LeftButton))
    {
        if (o_Map->currentCoordinate() == MapCenter)
        {
            if (l_WayPoints.count() < 20)
            {
                pb_Add->setEnabled(true);
            }
            pb_Goto->setEnabled(true);

            o_Click->removeGeometry(ClickPoint);

            ClickPoint = new CirclePoint(Coord.x(), Coord.y(), 6, "P1", Point::Middle, Pen[1]);

            LastClick = new Point(Coord.x(), Coord.y());

            ClickPoint->setBaselevel(o_Adapter->adaptedZoom());
            o_Click->addGeometry(ClickPoint);
        }
    }

    o_Map->updateRequestNew();

//    qDebug(QString("%1").arg(Coord.x()).toLatin1().data());
//    qDebug(QString("%1").arg(Coord.y()).toLatin1().data());
}


void dlg_Map::slot_LoadMapPic()
{
    QString Filename = QFileDialog::getOpenFileName(this, "Bild als Karte",  o_Settings->DIR.Logging, "Bilddatei(*.jpg *.png *.gif);;Alle Dateien (*)");

    if (!Filename.isEmpty())
    {
        QFile *f_Points = new QFile(Filename + ".pos");

        if (f_Points->exists())
        {
            f_Points->open(QIODevice::ReadOnly | QIODevice::Text);

            QString s_Points;

            while (!f_Points->atEnd())
            {
                s_Points.append(f_Points->readLine());
            }

            f_Points->close();

            QStringList s_Pos = s_Points.split(",");

            FixedImageOverlay* fip = new FixedImageOverlay(s_Pos[0].toDouble(), s_Pos[1].toDouble(), s_Pos[2].toDouble(), s_Pos[3].toDouble(), Filename);

            o_Layer->addGeometry(fip);
            o_Map->updateRequestNew();
        }
        else
        {
            dlg_MapPos *f_MapPos = new dlg_MapPos(this);

            if (f_MapPos->exec()==QDialog::Accepted)
            {
                QString Data = f_MapPos->get_Data();

                f_Points->open(QIODevice::ReadWrite | QIODevice::Text);

                QTextStream out(f_Points);

                out.setRealNumberPrecision(9);

                out << Data << "\n";

                f_Points->close();

                QStringList s_Pos = Data.split(",");

                FixedImageOverlay* fip = new FixedImageOverlay(s_Pos[0].toDouble(), s_Pos[1].toDouble(), s_Pos[2].toDouble(), s_Pos[3].toDouble(), Filename);

                o_Layer->addGeometry(fip);
                o_Map->updateRequestNew();
            }

        }
    }
}

// auf Veränderung der Fenstergröße reagieren
void dlg_Map::resizeEvent ( QResizeEvent * event )
{
    event = event;
    o_Map->resize(w_Map->size() - QSize(20,20));
}

// Karte wechseln
void dlg_Map::slot_ChangeMap(int t_Set)
{
    int zoom = o_Adapter->adaptedZoom();
    QPointF a = o_Map->currentCoordinate();

    o_Map->setZoom(0);

    switch(t_Set)
    {
        case 0 : // OpenStreetMap
        {
            o_Adapter = new OSMMapAdapter();
        }
        break;
        case 1 : // Yahoo Sat
        {
            o_Adapter = new TileMapAdapter("tile.openaerialmap.org", "/tiles/1.0.0/openaerialmap-900913/%1/%2/%3.png", 256, 0, 17);
        }
        break;
        case 2 : // Google Maps
        {
            o_Adapter = new GoogleMapAdapter();
        }
        break;
        case 3 : // Google Sat
        {
            o_Adapter = new GoogleSatMapAdapter();
        }
        break;
        case 4 : // Yahoo Maps
        {
            o_Adapter = new YahooMapAdapter();
        }
        break;
        case 5 : // Yahoo Sat
        {
            o_Adapter = new YahooMapAdapter("us.maps3.yimg.com", "/aerial.maps.yimg.com/png?v=1.7&t=a&s=256&x=%2&y=%3&z=%1");
        }
        break;
    }

    o_Layer->setMapAdapter(o_Adapter);
    o_Click->setMapAdapter(o_Adapter);
    o_Route->setMapAdapter(o_Adapter);

    o_Map->updateRequestNew();
    o_Map->setZoom(zoom);
}

// Fenster wird geschlossen.
void dlg_Map::slot_Close()
{
    o_Settings->Map.GotoPosition = cb_CenterPos->isChecked();
    o_Settings->Map.ShowTrack    = cb_ShowRoute->isChecked();
    emit set_Settings(o_Settings);
}

