/**********************************************************************************************
    Copyright (C) 2014 Oliver Eichler <oliver.eichler@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 3 of the License, or
    (at your option) any later version.

    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, see <http://www.gnu.org/licenses/>.

**********************************************************************************************/

#include "CQlgtRoute.h"

struct rte_head_entry_t {
  rte_head_entry_t() : type(CQlgtRoute::eEnd), offset(0) {}
  qint32 type;
  quint32 offset;
  QByteArray data;
};

QDataStream& operator>>(QDataStream& s, CQlgtRoute& route) {
  quint32 nRtePts = 0;
  QIODevice* dev = s.device();
  qint64 pos = dev->pos();

  char magic[9];
  s.readRawData(magic, 9);

  if (strncmp(magic, "QLRte   ", 9)) {
    dev->seek(pos);
    return s;
  }

  QList<rte_head_entry_t> entries;

  while (1) {
    rte_head_entry_t entry;
    s >> entry.type >> entry.offset;
    entries << entry;
    if (entry.type == CQlgtRoute::eEnd) {
      break;
    }
  }

  QList<rte_head_entry_t>::iterator entry = entries.begin();
  while (entry != entries.end()) {
    qint64 o = pos + entry->offset;
    dev->seek(o);
    s >> entry->data;

    switch (entry->type) {
      case CQlgtRoute::eBase: {
        QDataStream s1(&entry->data, QIODevice::ReadOnly);
        s1.setVersion(QDataStream::Qt_4_5);

        s1 >> route.key;
        s1 >> route.timestamp;
        s1 >> route.name;
        s1 >> route.iconString;
        s1 >> route.ttime;
        s1 >> route.parentWpt;

        break;
      }

      case CQlgtRoute::eRtePts: {
        QDataStream s1(&entry->data, QIODevice::ReadOnly);
        s1.setVersion(QDataStream::Qt_4_5);
        quint32 n;

        route.priRoute.clear();
        s1 >> nRtePts;

        for (n = 0; n < nRtePts; ++n) {
          CQlgtRoute::pt_t rtept;
          float u, v;
          QString action;

          s1 >> u;
          s1 >> v;
          s1 >> action;

          rtept.lon = u;
          rtept.lat = v;
          rtept.action = action;
          route.priRoute << rtept;
        }
        break;
      }
        //            case CQlgtRoute::eRteSec:
        //            {
        //                QDataStream s1(&entry->data, QIODevice::ReadOnly);
        //                s1.setVersion(QDataStream::Qt_4_5);
        //                quint32 n;

        //                route.secRoute.clear();
        //                s1 >> nRtePts;

        //                for(n = 0; n < nRtePts; ++n)
        //                {
        //                    CQlgtRoute::pt_t rtept;
        //                    float u, v;
        //                    QString action;

        //                    s1 >> u;
        //                    s1 >> v;
        //                    s1 >> action;

        //                    rtept.lon = u;
        //                    rtept.lat = v;
        //                    rtept.action = action;
        //                    route.secRoute << rtept;
        //                }
        //                break;
        //            }
      default:;
    }

    ++entry;
  }

  return s;
}

QDataStream& operator<<(QDataStream& s, CQlgtRoute& route) {
  QList<rte_head_entry_t> entries;

  //---------------------------------------
  // prepare base data
  //---------------------------------------
  rte_head_entry_t entryBase;
  entryBase.type = CQlgtRoute::eBase;
  QDataStream s1(&entryBase.data, QIODevice::WriteOnly);
  s1.setVersion(QDataStream::Qt_4_5);

  s1 << route.key;
  s1 << route.timestamp;
  s1 << route.name;
  s1 << route.iconString;
  s1 << route.ttime;
  s1 << route.parentWpt;

  entries << entryBase;

  //---------------------------------------
  // prepare primary routepoint data
  //---------------------------------------
  rte_head_entry_t entryPriRtePts;
  entryPriRtePts.type = CQlgtRoute::eRtePts;
  QDataStream s2(&entryPriRtePts.data, QIODevice::WriteOnly);
  s2.setVersion(QDataStream::Qt_4_5);

  {
    QVector<CQlgtRoute::pt_t>& rtepts = route.priRoute;
    QVector<CQlgtRoute::pt_t>::iterator rtept = rtepts.begin();

    s2 << (quint32)rtepts.size();
    while (rtept != rtepts.end()) {
      s2 << (float)rtept->lon;
      s2 << (float)rtept->lat;
      s2 << rtept->action;
      ++rtept;
    }
  }
  entries << entryPriRtePts;

  //    //---------------------------------------
  //    // prepare secondary routepoint data
  //    //---------------------------------------
  //    rte_head_entry_t entrySecRtePts;
  //    entrySecRtePts.type = CQlgtRoute::eRteSec;
  //    QDataStream s3(&entrySecRtePts.data, QIODevice::WriteOnly);
  //    s3.setVersion(QDataStream::Qt_4_5);

  //    {
  //        QVector<CQlgtRoute::pt_t>& rtepts           = route.getSecRtePoints();
  //        QVector<CQlgtRoute::pt_t>::iterator rtept   = rtepts.begin();

  //        if(!rtepts.isEmpty())
  //        {
  //            s3 << (quint32)rtepts.size();
  //            while(rtept != rtepts.end())
  //            {
  //                s3 << (float)rtept->lon;
  //                s3 << (float)rtept->lat;
  //                s3 << rtept->action;
  //                ++rtept;
  //            }
  //            entries << entrySecRtePts;
  //        }

  //    }

  //---------------------------------------
  // prepare terminator
  //---------------------------------------
  rte_head_entry_t entryEnd;
  entryEnd.type = CQlgtRoute::eEnd;
  entries << entryEnd;

  //---------------------------------------
  //---------------------------------------
  // now start to actually write data;
  //---------------------------------------
  //---------------------------------------
  // write magic key
  s.writeRawData("QLRte   ", 9);

  // calculate offset table
  quint32 offset = entries.count() * 8 + 9;

  QList<rte_head_entry_t>::iterator entry = entries.begin();
  while (entry != entries.end()) {
    entry->offset = offset;
    offset += entry->data.size() + sizeof(quint32);
    ++entry;
  }

  // write offset table
  entry = entries.begin();
  while (entry != entries.end()) {
    s << entry->type << entry->offset;
    ++entry;
  }

  // write entry data
  entry = entries.begin();
  while (entry != entries.end()) {
    s << entry->data;
    ++entry;
  }

  return s;
}

CQlgtRoute::CQlgtRoute(quint64 id, QObject* parent) : QObject(parent), IItem(id) {}

CQlgtRoute::~CQlgtRoute() {}
