/***********************************************************************
**
**   tasklist.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: tasklist.cpp,v 1.11 2004/06/16 16:06:10 axel Exp $
**
***********************************************************************/

#include <limits.h>
#include <qsplitter.h>
#include <qdir.h>
#include <qlayout.h>
#include <qtextstream.h>
#include <qpushbutton.h>
#include <qpe/resource.h>
#include <qmessagebox.h>

#include "tasklist.h"
#include "mapmatrix.h"
#include "mapcontents.h"
#include "taskdialog.h"
#include "distance.h"

uint TaskList::lastSelection = 0;

TaskList::TaskList( QWidget* parent, const char* name )
  : QWidget( parent, name ),
    editTask(0)
{
  taskList.setAutoDelete(true);

  QVBoxLayout* taskLayout = new QVBoxLayout( this, 5 );
  QHBoxLayout *editrow=new QHBoxLayout(taskLayout, 0);

  editrow->addStretch(10);
  
  QPushButton * cmdNew = new QPushButton(this);
  cmdNew->setPixmap(Resource::loadPixmap("new"));
  cmdNew->setFlat(true);
  editrow->addWidget(cmdNew);
  
  QPushButton * cmdEdit = new QPushButton(this);
  cmdEdit->setPixmap(Resource::loadPixmap("edit"));
  cmdEdit->setFlat(true);
  editrow->addWidget(cmdEdit);
  
  QPushButton * cmdDel = new QPushButton(this);
  cmdDel->setPixmap(Resource::loadPixmap("trash"));
  cmdDel->setFlat(true);
  editrow->addWidget(cmdDel);

#ifndef QT_NO_SPLITTER
  QSplitter* splitter = new QSplitter( Vertical, this, "Splitter" );
  splitter->setOpaqueResize( true );
  taskListView = new QListView( splitter );
#else
  taskListView = new QListView( this );
#endif

  taskListView->addColumn( tr("No"), 20 );
  taskListView->addColumn( tr("Name") );
  taskListView->addColumn( tr("Type") );
  taskListView->addColumn( tr("Distance") );
  taskListView->setAllColumnsShowFocus( true );
  taskListView->setMinimumHeight(1);
  taskListView->setFocus();

#ifndef QT_NO_SPLITTER
  taskRoute = new QTextView( splitter );
#else
  taskRoute = new QTextView( this );
#endif

  taskRoute->setHScrollBarMode( QTextView::AlwaysOff );
  taskRoute->setMinimumSize(1,100); //somehow, the layout alone doesn't cut it.

#ifndef QT_NO_SPLITTER  
  taskLayout->addWidget( splitter, 1 );
#else
  taskLayout->addWidget( taskListView,1);
  taskLayout->addWidget( taskRoute,2);
#endif

  connect(cmdNew, SIGNAL(clicked()), this, SLOT(slotNewTask()));
  connect(cmdEdit, SIGNAL(clicked()), this, SLOT(slotEditTask()));
  connect(cmdDel, SIGNAL(clicked()), this, SLOT(slotDeleteTask()));

  connect( taskListView, SIGNAL( selectionChanged() ),
	   this, SLOT( slotTaskDetails() ) );

  if( ! slotLoadTask() )
    {
      return;
    }
}

TaskList::~TaskList()
{
  qDebug("TaskList::~TaskList()");
}

void TaskList::slotTaskDetails()
{
  if( taskListView->selectedItem() == 0 )
    return;

  if ((QString)taskListView->selectedItem()->text( 0 )==" ") {
    taskRoute->setText("");
    if (taskListView->selectedItem()->text( 1 )==tr("(No tasks defined)")) {
      taskRoute->setText(tr("Tip on editor icon, to define tasks."));
    };
    return;
  }

  int id( ((QString)taskListView->selectedItem()->text( 0 ) ).toInt() - 1 );

  QList<wayPoint> wpList = taskList.at( id )->getWPList();

  QString route;
  taskRoute->setText( "" );

  QString con( "" );

  for(unsigned int loop = 0; loop < wpList.count(); loop++)
    {
      route += con + wpList.at(loop)->description +
          " (" + wpList.at(loop)->name + ")";
      con = " -> ";
      if (loop==0) route += " <B>" + tr("(takeoff)") + "</B>";
      if (loop==1) route += " <B>" + tr("(start)") + "</B>";
      if (loop==wpList.count()-2) route += " <B>" + tr("(finish)") + "</B>";
      if (loop==wpList.count()-1) route += " <B>" + tr("(landing)") + "</B>";
    }
  taskRoute->setText("<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0  WIDTH=100%><TR><TD>" +
      route + "</TD></TR></TABLE>");
}

FlightTask* TaskList::selectedTask()
{
  // qDebug("TaskList::selectedTask()");

  if( taskListView->selectedItem() == NULL )
    return (FlightTask *)0;

  QString id( taskListView->selectedItem()->text(0) );

  if (id==" ") 
    {
      lastSelection = 0;
      return 0;
    }
  
  // qDebug("selected Item=%s",id.latin1());
  lastSelection = id.toUInt();

  // Nice trick, take selected element from list to prevent deletion of it, if
  // destruction of list is called.
  return taskList.take( id.toInt() - 1 );
}

/** load tasks from file*/
bool TaskList::slotLoadTask()
{
  extern MapMatrix * _globalMapMatrix;
  extern MapContents * _globalMapContents;

  _globalMapContents->setCurrentTask(0);

  taskList.clear();

  // currently hardcoded ...
  QFile f( QDir::homeDirPath() + "/tasks.tsk" );

  if( !f.open( IO_ReadOnly ) )
    {
      // could not read file ...
      taskListView->insertItem(new QListViewItem( taskListView, " ",
						  tr("(No tasks defined)")));
      return false;
    }

  QTextStream stream( &f );
  QString line;
  bool isTask( false );
  QString numTask, taskName;
  QStringList tmpList;
  QStringList::Iterator it;
  wayPoint* wp;
  QList<wayPoint> wpList;
  wpList.setAutoDelete(true);

  while( !stream.eof() )
    {
      line = stream.readLine();

      if( line.mid( 0, 1 ) == "#" ) continue;

      if( line.mid( 0, 2 ) == "TS" )
        {
          // new task ...
          isTask = true;
          tmpList = QStringList::split( ",", line, true );
          it = tmpList.at( 1 );
          taskName = (*it).latin1();
        }
      else if( line.mid( 0, 2 ) == "TW" && isTask )
        {
          // new wp ...
          wpList.append( new wayPoint );
          wp = wpList.current();

          tmpList = QStringList::split( ",", line, true );
          wp->origP.setLat( ( (QString)( *tmpList.at( 1 ) ).latin1() ).toInt() );
          wp->origP.setLon( ( (QString)( *tmpList.at( 2 ) ).latin1() ).toInt() );
          wp->projP = _globalMapMatrix->wgsToMap( wp->origP );
          wp->elevation = ( (QString)( *tmpList.at( 3 ) ).latin1() ).toInt();
          wp->name = ( *tmpList.at( 4 ) ).latin1();
          wp->icao = ( *tmpList.at( 5 ) ).latin1();
          wp->description = ( *tmpList.at( 6 ) ).latin1();
          wp->frequency = ( (QString)( *tmpList.at( 7 ) ).latin1() ).toDouble();
        }
      else if( line.mid( 0, 2 ) == "TE" && isTask )
        {
          // task complete
          isTask = false;
          taskList.append( new FlightTask( wpList, true, taskName ) );
          numTask.sprintf( "%d", taskList.count() );

	  QListViewItem *newItem = new QListViewItem( taskListView, numTask,
						      taskName, taskList.current()->getTaskTypeString(),
						      taskList.current()->getTaskDistanceString() );
          taskListView->insertItem(newItem);

	  if( taskList.count() == lastSelection )
	    {
	      // restore last selection
	      taskListView->setSelected( newItem, true );
	    }

          wpList.clear();
        }
    }

  f.close();

  if (taskList.count()==0)
    {
      taskListView->insertItem(new QListViewItem( taskListView, " ", tr("(No tasks defined)")));
    }
  else
    {
      taskListView->insertItem(new QListViewItem( taskListView, " ", tr("(Reset selection)"), tr("none")));
    }

  return true;
}

void TaskList::slotNewTask()
{
  TaskDialog *td = new TaskDialog(this, "TaskListDialog");

  connect( td, SIGNAL(newTask( FlightTask * )), this,
	   SLOT(slotUpdateTaskList( FlightTask * )));

  td->show();
}

/**
 * overtake a new flight task from editor
 */

void TaskList::slotUpdateTaskList( FlightTask *newTask)
{
  taskList.append( newTask );
  saveTaskList();
  taskRoute->setText("");
  taskListView->clear();
  slotLoadTask();
}

/**
 * pass the selected task to the editor
 */

void TaskList::slotEditTask()
{
  // fetch selected task item
  if( taskListView->selectedItem() == 0 )
    {
      return;
    }

  QString id( taskListView->selectedItem()->text(0) );

  if( id == " ") 
    {
      return;
    }

  lastSelection = id.toUInt();
  editTask = taskList.at(id.toInt() - 1);

  // make a deep copy of fetched task item

  FlightTask* modTask = new FlightTask( editTask->getWPList(), false,
					editTask->getTaskName() );

  TaskDialog *td = new TaskDialog(this, "TaskListDialog", modTask );

  connect( td, SIGNAL(editedTask( FlightTask * )), this,
	   SLOT(slotEditTaskList( FlightTask * )));

  td->show();
}

/**
 * overtake an edited flight task from editor
 */

void TaskList::slotEditTaskList( FlightTask *editedTask)
{
  qDebug("TaskList::slotEditTaskList()");

  // search task item being edited
  int index = taskList.findRef( editTask );

  if( index != -1 )
    {
      // remove old item
      taskList.remove( (uint) index );
      // put new item on old position
      taskList.insert( (uint) index, editedTask );
    }
  else
    {
      // no old position available, append it at end of list
      taskList.append( editedTask );
    }

  saveTaskList();
  taskRoute->setText("");
  taskListView->clear();
  slotLoadTask();
}

/**
 * remove the selected task from the list
 */

void TaskList::slotDeleteTask()
{
  if( taskListView->selectedItem() == 0 )
    {
      return;
    }

  QString id( taskListView->selectedItem()->text(0) );

  if( id == " " )
    {
      // Entries with no number are system specific and not deleteable
      return;
    }

  int answer=
    QMessageBox::warning(this,tr("Delete task?"),
			 tr("<qt>"
			    "Do you want to delete the selected task?"
			    "</qt>"),
			 QMessageBox::Ok | QMessageBox::Default,
			 QMessageBox::Cancel | QMessageBox::Escape );
  if( answer != 1 )
    {
      return;
    }

  lastSelection = 0;

  // reset task
  extern MapContents * _globalMapContents;
  _globalMapContents->setCurrentTask(0);

  uint no = id.toUInt() - 1;
  taskList.remove( no );
  saveTaskList();

  taskRoute->setText("");
  taskListView->clear();
  slotLoadTask();
}

bool TaskList::saveTaskList()
{
  // currently hardcoded ...
  QFile f( QDir::homeDirPath() + "/tasks.tsk" );

  if( !f.open( IO_WriteOnly ) )
    {
      qWarning( "Could not write to task-file %s", f.name().latin1() );
      return false;
    }

  QTextStream stream( &f );

  // writing file-header
  stream << "# KFLog-Task-File" << endl;

  for( uint i=0; i < taskList.count(); i++ )
    {
      FlightTask *task = taskList.at(i);
      QList<wayPoint> wpList = task->getWPList();

      stream << "TS," << task->getTaskName() << "," 
	     << wpList.count() << endl;

      for( uint j=0; j < wpList.count(); j++ )
	{
	  // saving each waypoint ...
	  wayPoint* wp = wpList.at(j);
	  stream << "TW," << wp->origP.x() << "," << wp->origP.y() << ","
		 << wp->elevation << "," << wp->name << "," << wp->icao << ","
		 << wp->description << "," << wp->frequency << ","
		 << wp->comment << "," << wp->isLandable << wp->runway << ","
		 << wp->length << "," << wp->surface
		 << endl;
	}

      stream << "TE" << endl;
    }

  f.close();

  return true;
}
