/***************************************************************************
**
**  This file is part of geopsy.
**
**  geopsy 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.
**
**  geopsy 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 Foobar.  If not, see <http://www.gnu.org/licenses/>
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2007-02-19
**  Copyright: 2007-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <GeopsyCore.h>
#include <GeopsyGui.h>

#include "FileView.h"
#include "Engine.h"
#include "SigSelectionDnD.h"
#include "MainWindow.h"
#include "ToolFactory.h"

/*!
  \class FileView FileView.h
  \brief Brief description of class still missing

  Full description of class still missing
*/

/*!
  Description of constructor still missing
*/
FileView::FileView(QWidget* parent)
    : QTreeView(parent)
{
  TRACE;
  SigSelectionDnD * sigDnD=new SigSelectionDnD(this);
  viewport()->installEventFilter(sigDnD);
  sigDnD->setDropEnabled(false);
  connect(sigDnD, SIGNAL(getSelection(SubSignalPool&)),
           this, SLOT(getSelection( SubSignalPool& )));

  _menu=new QMenu(this);
  setContextMenuPolicy(Qt::DefaultContextMenu);

  SignalFileItem * model=new SignalFileItem(Engine::instance()->database(this), this);
  header()->hide();
  setRootIsDecorated(false);
  setModel(model);
  setSelectionBehavior(QAbstractItemView::SelectRows);
  setSelectionMode(QAbstractItemView::ExtendedSelection);
  setEditTriggers(QAbstractItemView::NoEditTriggers);
  setColumnWidth(0,250);
}

void FileView::addActions()
{
  TRACE;

  MainWindow * mw=WindowEnvironment::instance()->window(this);
  _tableAction=MainWindow::newAction(*mw->viewTableAction(), this);
  connect(_tableAction, SIGNAL(triggered()), this, SLOT(newTableWindow()));
  _graphicAction=MainWindow::newAction(*mw->viewGraphicAction(), this);
  connect(_graphicAction, SIGNAL(triggered()), this, SLOT(newGraphicWindow()));
  _mapAction=MainWindow::newAction(*mw->viewMapAction(), this);
  connect(_mapAction, SIGNAL(triggered()), this, SLOT(newMapWindow()));
  _chronogramAction=MainWindow::newAction(*mw->viewChronogramAction(), this);
  connect(_chronogramAction, SIGNAL(triggered()), this, SLOT(newChronogramWindow()));
}

SignalFileItem * FileView::model() const
{
  TRACE;
  return static_cast<SignalFileItem *>(QTreeView::model());
}

void FileView::beginReset()
{
  TRACE;
  model()->beginReset();
}

void FileView::endReset()
{
  TRACE;
  model()->endReset();
}

void FileView::beginAddFile()
{
  TRACE;
  model()->beginAddFile();
}

void FileView::endAddFile()
{
  TRACE;
  model()->endAddFile();
}

void FileView::getSelection(SubSignalPool& sel)
{
  TRACE;
  model()->getSelection(sel, *selectionModel());
}

QSize FileView::sizeHint() const
{
  TRACE;
  return QSize(200, -1);
}

void FileView::contextMenuEvent(QContextMenuEvent * e)
{
  TRACE;
  _menu->clear();

  QModelIndex index=indexAt(e->pos());
  if(index.isValid()) {
    QItemSelectionModel& sm=*selectionModel();
    if(!sm.isSelected(index)) {
      sm.select(index, QItemSelectionModel::ClearAndSelect);
    }
    _menu->addAction(_tableAction);
    _menu->addAction(_graphicAction);
    _menu->addAction(_mapAction);
    _menu->addAction(_chronogramAction);
    _menu->addSeparator();
    MainWindow * mw=WindowEnvironment::window(this);
    if(mw->toolFactory()->addPopularActions(_menu, this, SLOT(newTool()))) {
      _menu->addSeparator();
    }
    _menu->addAction(tr("Remove"), this, SLOT(remove()));
    _menu->addAction(tr("Copy path"), this, SLOT(copyPath()));
    _menu->popup(mapToGlobal( e->pos()) );
  }
}

void FileView::mouseDoubleClickEvent (QMouseEvent * e)
{
  TRACE;
  QModelIndex index=indexAt(e->pos());
  if(index.isValid()) newGraphicWindow();
}

SubPoolWindow * FileView::newTableWindow()
{
  TRACE;
  SubSignalPool sel;
  getSelection(sel);
  return GeopsyGuiEngine::instance()->newTableWindow(this, sel);
}

SubPoolWindow * FileView::newGraphicWindow()
{
  TRACE;
  SubSignalPool sel;
  getSelection(sel);
  return GeopsyGuiEngine::instance()->newGraphicWindow(this, sel);
}

SubPoolWindow * FileView::newMapWindow()
{
  TRACE;
  SubSignalPool sel;
  getSelection(sel);
  return GeopsyGuiEngine::instance()->newMapWindow(this, sel);
}

SubPoolWindow * FileView::newChronogramWindow()
{
  TRACE;
  SubSignalPool sel;
  getSelection(sel);
  return GeopsyGuiEngine::instance()->newChronogramWindow(this, sel);
}

void FileView::newTool()
{
  TRACE;
  QAction * a=qobject_cast<QAction *>(sender());
  if(a) {
    QAction * original=*reinterpret_cast<QAction **>(a->data().toByteArray().data());
    MainWindow * mw=WindowEnvironment::window(this);
    mw->toolFactory()->showTool(newGraphicWindow(), original);
  }
}

void FileView::remove()
{
  TRACE;
  static const QString title=tr("Removing files from database");
  QList<SignalFile *> fList;
  model()->getSelection(fList, *selectionModel());
  if(fList.isEmpty()) {
    Message::warning(MSG_ID, title, tr("No file selected for removal."), Message::ok());
    return;
  }
  QString fileListStr;
  for(QList<SignalFile *>::Iterator it=fList.begin();it!=fList.end();++it) {
    fileListStr+=((*it)->isOriginalFile() ? "\nO " : "\n  ")+(*it)->name();
  }
  if(Message::warning(MSG_ID, title,
                            tr("List of file(s) to remove:\n%1\n\n"
                               "Original files (marked with 'O') will not be erased from disk. "
                               "All other files automatically produced by Geopsy will be erased "
                               "from the disk.\n\nDo you really want to remove these files?").arg(fileListStr),
                            Message::no(), Message::yes())==Message::Answer0) return ;
  MainWindow * mw=WindowEnvironment::instance()->window(this);
  if(!mw->subWindowList().isEmpty()) {
    if(Message::warning(MSG_ID, title,
                        tr("Closing all opened window is mandatory before removing "
                           "a file. Do you want to close all windows?"),
                        Message::no(), Message::yes())==Message::Answer0) return;
    mw->closeAllSubWindowsFromAllTabs();
    qApp->processEvents(QEventLoop::ExcludeUserInputEvents); // wait for all windows to be closed
  }
  mw->filesRemoved(fList);
  model()->remove(fList);
}

void FileView::copyPath()
{
  TRACE;
  QList<SignalFile *> fList;
  model()->getSelection(fList, *selectionModel());
  QString fileListStr;
  int n=fileListStr.count()-1;
  if(!fList.isEmpty()) {
    for(int i=0; i<n; i++) {
      fileListStr+=fList.at(i)->name()+"\n";
    }
    fileListStr+=fList.last()->name();
    QClipboard * cb=QApplication::clipboard();
    cb->setText(fileListStr, QClipboard::Clipboard);
#ifdef Q_OS_LINUX
    cb->setText(fileListStr, QClipboard::Selection);
#endif
  }
}
