/***********************************************************************
**
**   task.cpp
**
**   This file is part of KFLogEmbedded.
**
************************************************************************
**
**   Copyright (c):  2002 by Heiner Lamprecht
**
**   This file is distributed under the terms of the General Public
**   Licence. See the file COPYING for more information.
**
**   $Id: taskdialog.cpp,v 1.5 2005/02/18 21:57:03 axel Exp $
**
***********************************************************************/

#include <qdatastream.h>
#include <qdir.h>
#include <qfile.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qstring.h>
#include <qmessagebox.h>
#include <qpushbutton.h>
#include <qtextstream.h>

#include "taskdialog.h"
#include "mapcontents.h"
#include "flighttask.h"
#include "distance.h"

#define KFLOG_FILE_MAGIC    0x404b464c
#define FILE_TYPE_WAYPOINTS 0x50
#define FILE_FORMAT_ID      100

#define FILE_TYPE_TASKS     0x74
#define FILE_TASKS_FORMAT_ID 100

#include <qpe/applnk.h>
#include <qpe/global.h>
#include <qpe/resource.h>

TaskDialog::TaskDialog( QWidget* parent, const char* name, FlightTask* task )
  : QDialog( parent, name, false, Qt::WStyle_StaysOnTop )
{
  wpList.setAutoDelete(true);
  taskWPList.setAutoDelete(true);
  lastSelectedItem = -1;

  if( task )
    {
      planTask = task;
      editState = TaskDialog::edit;
      this->setCaption(planTask->getTaskTypeString());
    }
  else
    {
      planTask = new FlightTask( tr("unknown") );
      editState = TaskDialog::create;
      this->setCaption(tr("New Task"));
    }

  taskName = new QLineEdit( this );
  taskName->setBackgroundMode( PaletteLight );

  taskList = new QListView( this, "taskList" );
  taskList->addColumn( tr("Id"), 16 );
  taskList->addColumn( tr("Type"), 45 );
  taskList->addColumn( tr("Waypoint"), 90 );
  taskList->addColumn( tr("Distance"), 60 );
  taskList->setMinimumHeight( 100 );
  taskList->setMaximumHeight( 120 );
  taskList->setAllColumnsShowFocus( true );

  waypointList = new QListView( this, "waypointList" );
  waypointList->addColumn( tr("Name") );
  waypointList->addColumn( tr("ICAO") );
  waypointList->addColumn( tr("Description") );
  waypointList->setAllColumnsShowFocus( true );

  waypointList->setFocus();

  QPushButton* upButton = new QPushButton( this );
  upButton->setPixmap( Resource::loadPixmap( "cumulus/moveup.png") );
  upButton->setFlat(true);
 
  QPushButton* downButton = new QPushButton( this );
  downButton->setPixmap( Resource::loadPixmap( "cumulus/movedown.png") );
  downButton->setFlat(true);

  QPushButton* invertButton = new QPushButton( this );
  invertButton->setPixmap( Resource::loadPixmap( "cumulus/invert.png") );
  invertButton->setFlat(true);

  QPushButton* addButton = new QPushButton( this );
  addButton->setPixmap( Resource::loadPixmap( "cumulus/moveup.png") );
  addButton->setFlat(true);

  QPushButton* delButton = new QPushButton( this );
  delButton->setPixmap( Resource::loadPixmap( "cumulus/movedown.png") );
  delButton->setFlat(true);

  QGridLayout* taskLayout = new QGridLayout( this, 12, 8, 2, 1);

  taskLayout->addMultiCellWidget( new QLabel( tr("Task Name:"), this ), 0, 0, 0, 0 );
  taskLayout->addMultiCellWidget( taskName, 0, 0, 1, 6 );
  taskLayout->addMultiCellWidget( taskList, 2, 6, 0, 6 );
  taskLayout->addWidget( invertButton, 3, 7, AlignCenter );
  taskLayout->addWidget( upButton, 4, 7, AlignCenter );
  taskLayout->addWidget( downButton, 5, 7, AlignCenter );

  taskLayout->addWidget( new QLabel( tr("Waypoint list:"), this ), 8, 0 );
  taskLayout->addWidget( addButton, 8, 2, AlignCenter  );
  taskLayout->addWidget( delButton, 8, 3, AlignCenter  );

  filter = new ListViewFilter(waypointList, this, "listfilter");
  taskLayout->addMultiCellWidget( filter, 10, 10, 0, 7 );
  taskLayout->addMultiCellWidget( waypointList, 11, 11, 0, 7 );

  taskLayout->addRowSpacing( 7, 2 );
  taskLayout->addRowSpacing( 9, 2 );

  if( editState == TaskDialog::edit )
    {
      taskName->setText( planTask->getTaskName() );

      QList<wayPoint> tmpList = planTask->getWPList();

      // @AP: Make a deep copy from all elements of the list
      for( uint i=0; i < tmpList.count(); i++ )
	{
	  taskWPList.append( new wayPoint(*tmpList.at(i)) );
	}

      __showTask();
    }

  QString fName = QDir::homeDirPath() + "/Applications/cumulus/cumulus.kwp";

  __readWaypointList( fName );
  __showWPList();

  connect( addButton,    SIGNAL( clicked() ), this, SLOT( slotAddWaypoint() ) );
  connect( delButton,    SIGNAL( clicked() ), this, SLOT( slotRemoveWaypoint() ) );
  connect( upButton,     SIGNAL( clicked() ), this, SLOT( slotMoveWaypointUp() ) );
  connect( downButton,   SIGNAL( clicked() ), this, SLOT( slotMoveWaypointDown() ) );
  connect( invertButton, SIGNAL( clicked() ), this, SLOT( slotInvertWaypoints() ) );

  showMaximized();
}

TaskDialog::~TaskDialog()
{
  waypointList->clear();
  qDebug("TaskDialog::~TaskDialog()");
}

bool TaskDialog::__readWaypointList(const QString& fileName)
{
  Q_UINT32 magic;
  Q_INT8 typeID;
  Q_INT16 formatID;

  QString wpName="";
  QString wpDescription="";
  QString wpICAO="";
  Q_INT8 wpType;
  Q_INT32 wpLatitude;
  Q_INT32 wpLongitude;
  Q_INT16 wpElevation;
  double wpFrequency=0.;
  Q_INT8 wpLandable;
  Q_INT16 wpRunway;
  Q_INT16 wpLength;
  Q_INT8 wpSurface;
  QString wpComment="";
  Q_UINT8 wpImportance;

  QFile f(fileName);

  if( !f.exists() )
    {
      QMessageBox::warning( 0,
        ((QString)"<B>%1</B><BR>not found!").arg( fileName ),
        "Error occurred!");
      return false;
    }

  if( !f.open(IO_ReadOnly) )
    {
      //
      QMessageBox::warning( 0,
          ((QString)"<B>%1</B><BR>permission denied!").arg( fileName ),
          "Error occurred!");
      return false;
    }

  QDataStream in(&f);
  in.setVersion(2);

  in >> magic;
  if(magic != KFLOG_FILE_MAGIC)
    {
      QMessageBox::warning( 0, "wrong file-format",
        "Can't read the waypoint catalog" );
      return false;
    }

  in >> typeID;

  if(typeID != FILE_TYPE_WAYPOINTS)
    {
      QMessageBox::warning( 0, "wrong file",
          "The selected file is no waypoint catalog" );
      return false;
    }

  in >> formatID;
  if(formatID < FILE_FORMAT_ID)
    {
      // too old ...
      return false;
    }
  else if(formatID > FILE_FORMAT_ID + 1)
    {
      // too young ...
      return false;
    }

  while(!in.eof())
    {
      // read values from file
      in >> wpName;
      in >> wpDescription;
      in >> wpICAO;
      in >> wpType;
      in >> wpLatitude;
      in >> wpLongitude;
      in >> wpElevation;
      in >> wpFrequency;
      in >> wpLandable;
      in >> wpRunway;
      in >> wpLength;
      in >> wpSurface;
      in >> wpComment;
      if (formatID==FILE_FORMAT_ID+1) { //newer, with 'importance field'
        in >> wpImportance;
      } else {
	wpImportance=1; //normal importance
      };
      
      // create new waypoint object and set the correct properties
      wayPoint *w = new wayPoint();

      w->name = wpName;
      w->description = wpDescription;
      w->icao = wpICAO;
      w->type = wpType;
      w->origP.setLat(wpLatitude);
      w->origP.setLon(wpLongitude);
      w->elevation = wpElevation;
      w->frequency = wpFrequency;
      w->isLandable = wpLandable;
      w->runway =wpRunway;
      w->length = wpLength;
      w->surface = wpSurface;
      w->comment = wpComment;
      w->importance = wpImportance;
      //qDebug("Waypoint read: %s (%s - %s)",w->name.latin1(),w->description.latin1(),w->icao.latin1());

      wpList.append( w );
    }

  return true;
}

void TaskDialog::__showWPList()
{
  waypointList->clear();

  for(unsigned int loop = 0; loop < wpList.count(); loop++)
    {
      wayPoint* wp = wpList.at( loop );
      waypointList->insertItem( new QListViewItem( waypointList,
						   wp->name, wp->icao, wp->description ) );
    }

  filter->reset();
}

void TaskDialog::__showTask()
{
  if( taskWPList.count() == 0 )
    {
      this->setCaption(tr("New Task"));
      return;
    }

  planTask->setWaypointList( taskWPList );

  QString txt = planTask->getTaskTypeString() +
    " / " + planTask->getTaskDistanceString();

  this->setCaption(txt);

  QList<wayPoint> tmpList = planTask->getWPList();

  taskList->clear();

  QString typeName, distance, idString;

  for(unsigned int loop = 0; loop < tmpList.count(); loop++)
    {
      wayPoint* wp = tmpList.at( loop );

      switch( wp->type )
        {
          case FlightTask::TakeOff:
            typeName = tr("Take-off");
            break;
          case FlightTask::Begin:
            typeName = tr("Begin");
            break;
          case FlightTask::RouteP:
            typeName = tr("Route");
            break;
          case FlightTask::End:
            typeName = tr("End");
            break;
          case FlightTask::FreeP:
            typeName = tr("Free");
            break;
          case FlightTask::Landing:
            typeName = tr("Landing");
            break;
          case FlightTask::NotSet:
          default:
            typeName = tr("not set");
            break;
        }

      distance=Distance::getText(wp->distance*1000,true,2);
      //distance.sprintf( "%.2f km", wp->distance );
      idString.sprintf( "%d", loop );

      QListViewItem *newLvi =
	new QListViewItem( taskList,
			   idString, typeName, wp->name, distance );

      taskList->insertItem( newLvi );
 
      // reselect last selected item
      if( lastSelectedItem == (int) loop )
	{
	  taskList->setSelected( newLvi, true );
	  lastSelectedItem = -1;
	}
    }
}

void TaskDialog::slotAddWaypoint()
{
  if( waypointList->selectedItem() == 0 )
    {
      return;
    }

  QString name( waypointList->selectedItem()->text(0) );
  QString icao( waypointList->selectedItem()->text(1) );
  QString description( waypointList->selectedItem()->text(2) );

  for(unsigned int loop = 0; loop < wpList.count(); loop++)
    {
      wayPoint* wp = wpList.at( loop );
      if( wp->name == name &&
          wp->description == description &&
	  wp->icao == icao )
        {
          // Wegpunkt gefunden!
          // Wir müssen ihn kopieren, da sonst u.U. mehrmals
          // das physikalisch gleiche Element eingetragen wird.
          taskWPList.append( new wayPoint(*wp) );
        }
    }

  __showTask();
}

void TaskDialog::slotRemoveWaypoint()
{
  if( taskList->selectedItem() == 0 )
    {
      return;
    }

  int id( taskList->selectedItem()->text(0).toInt() );

  taskWPList.remove( id );
  taskList->takeItem( taskList->selectedItem() );

  __showTask();
}

void TaskDialog::slotInvertWaypoints()
{
  if( taskWPList.count() < 2 )
    {
      // not possible to invert order, if elements are less 2
      return;
    }
  
  // invert list order
  for( int i= (int) taskWPList.count()-2; i >= 0; i-- )
    {
      taskWPList.append( taskWPList.take(i) );
    }

  __showTask();
}

void TaskDialog::accept()
{
  qDebug("TaskDialog::accept()");
  if( taskWPList.count() == 0 )
    {
      return;
    }

  QString txt = taskName->text();

  if( txt.length() == 0 )
    {
      QMessageBox::warning(this,tr("Missing name?"),
			   tr("<qt>"
			      "Please enter a task name before exit!"
			      "</qt>"),
			   QMessageBox::Ok | QMessageBox::Default, 0 );
      return;
    }

  QDialog::accept();
  planTask->setTaskName(txt);

  if( editState == TaskDialog::create )
    {
      emit newTask( planTask );
    }
  else
    {
      emit editedTask( planTask );
    }

  planTask = 0;
  delete this;
}

void TaskDialog::reject()
{
  qDebug("TaskDialog::reject()");
  QDialog::reject();

  if( planTask )
    {
      delete planTask;
    }

  delete this;
}

void TaskDialog::slotMoveWaypointUp()
{
  if( taskList->selectedItem() == 0 || taskList->childCount() <= 2 )  
    return;

  unsigned int id( taskList->selectedItem()->text( 0 ).toInt() );
  // we can't  move the first item
  if( id == 0 )
    return;

  lastSelectedItem = id - 1;

  wayPoint* tmp = taskWPList.take( id );

  taskWPList.insert( id - 1, tmp );

  __showTask();
}

void TaskDialog::slotMoveWaypointDown()
{
  if( taskList->selectedItem() == 0 || taskList->childCount() <= 2 )  
    return;

  int id( taskList->selectedItem()->text( 0 ).toInt() );
  // we can't move the last item
  if( id == taskList->childCount() - 1 )
    return;

  lastSelectedItem = id + 1;

  wayPoint* tmp = taskWPList.take( id );

  taskWPList.insert( id + 1, tmp );

  __showTask();
}
