/***************************************************************************
**
**  This file is part of GeopsyGui.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file 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 Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2004-09-02
**  Copyright: 2004-2019
**    Marc Wathelet
**    Marc Wathelet (ULg, Liège, Belgium)
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QGpGuiTools.h>
#include "AbstractToolWidget.h"
#include "GeopsyGuiEngine.h"
#include "SubPoolWindow.h"

namespace GeopsyGui {

/*!
  \class AbstractToolWidget AbstractToolWidget.h
  \brief Basic functions useful for all geopsy tools

  Functions to re-implement are initStations, interface, updateAllFields,
  action, setParam
*/

AbstractToolWidget::AbstractToolWidget(QWidget * parent, int nChildren) :
  QWidget(parent)
{
  TRACE;
  _tool=nullptr;
  _subPoolWindow=nullptr;
  _signalLayer=nullptr;
  _pickLayer=nullptr;
  _timeWindowLayer=nullptr;
  // Init the children widget list
  _nChildren=nChildren;
  if(_nChildren>0) {
    _childrenList=new QWidget*[_nChildren];
    for(int i=0; i<_nChildren; i++) _childrenList[i]=nullptr;
  } else {
    _childrenList=nullptr;
  }
}

AbstractToolWidget::~AbstractToolWidget()
{
  TRACE;
  Settings::setWidget(this, objectName(), false);
  delete [] _childrenList;
  delete _tool;
}

bool AbstractToolWidget::setSubPool(SubPoolWindow * subPoolWin)
{
  TRACE;
  _subPoolWindow=subPoolWin;
  return setSubPool(&_subPoolWindow->subPool());
}

void AbstractToolWidget::closeEvent(QCloseEvent * e)
{
  TRACE;
  e->ignore();
}

/*!
  If re-implemented, call this base function before any other operation
*/
bool AbstractToolWidget::setSubPool(SubSignalPool * subPool)
{
  TRACE;
  bool ret;
  // Temporary work around during transition
  if(_tool) {
    ret=_tool->setSubPool(subPool);
  } else {
    // Use the old structure
    ret=initStations(subPool);
  }
  if(ret) {
    // setSubPool generally re-order signals
    emit updateSubPool();
  }
  return ret;
}


void AbstractToolWidget::restoreFields()
{
  TRACE;
  // Set default parameters as specified in parameter object
  // At this stage, tool parameters have defaults values
  if(_tool) { // It may be null for old tools that are still converted
    ASSERT(_tool->parameters());
    setParameters(_tool->parameters());
  }
  // Size is controlled by the parent widget
  parentWidget()->resize(parentWidget()->minimumSizeHint());
  Settings::getWidget(this, objectName(), false);
  // Size restore by MultiDocumentWindow is affected by the above statement
  // In case the user save a size, we reload it
  Settings::getSize(parentWidget(), objectName());
  updateAllFields();
}

void AbstractToolWidget::closeChildren()
{
  TRACE;
  for(int i=0;i<_nChildren;i++) {
    if(_childrenList[i]) {
      // Restore is handled by MultiDocumentWindow
      // MultiDocumentSubWindow does not setSize because widget is not userClosable.
      Settings::setSize(_childrenList[i]->parentWidget(), _childrenList[i]->objectName());
      GeopsyGuiEngine::instance()->removeSubWindow(_childrenList[i]);
      _childrenList[i]=nullptr;
    }
  }
}

void AbstractToolWidget::windowActivated()
{
  TRACE;
  MultiDocumentSubWindow * w=qobject_cast<MultiDocumentSubWindow *>(sender());
  if(w && w->widget()==this) {
    if(_subPoolWindow->isMinimized()) _subPoolWindow->showNormal();
    if(_subPoolWindow->parentWidget()) {
      _subPoolWindow->parentWidget()->raise();
    }
    for(int i=0;i<_nChildren;i++) {
      if(_childrenList[i]) {
        if(_childrenList[i]->isMinimized()) {
          _childrenList[i]->showNormal();
        }
        _childrenList[i]->parentWidget()->raise();
      }
    }
    parentWidget()->raise();
  }
}

/*!
  Copied from QDialog's implementation
*/
void AbstractToolWidget::contextMenuEvent(QContextMenuEvent *e)
{
  TRACE;
  QWidget* w=childAt(e->pos());
  if( !w) return;
  QString s;
  while(s.isEmpty() && w) {
    s=w->whatsThis();
    if(s.isEmpty()) w=w->parentWidget();
  }
  if(!s.isEmpty()) {
    QMenu p;
    QAction * a=p.addAction(tr("What's This?"));
    if(p.exec(e->globalPos())==a)
      QWhatsThis::showText(w->mapToGlobal(w->rect().center()), s, w);
  }
}

bool AbstractToolWidget::loadLogParameters(QString fileName)
{
  TRACE;
  if(fileName.isEmpty()) {
    fileName=Message::getOpenFileName(tr("Loading parameters in log file"),
                                          tr("Log file (*.log)"));
  }
  if(fileName.length()>0) {
    QFile f(fileName);
    if(!f.open(QIODevice::ReadOnly)) {
      Message::warning(MSG_ID, tr("Loading parameters in log file"),
                           tr("Unable to open file for reading"), Message::cancel());
      return false;
    }
    QTextStream s(&f);
    AbstractParameters * param=parameters();
    if(param->load(s, "# BEGIN PARAMETERS", "# END PARAMETERS")) {
      updateAllFields(); // required?
      setParameters(param);
      return true;
    }
  }
  return false;
}

void AbstractToolWidget::saveLogParameters(QString fileName)
{
  TRACE;
  if(fileName.isEmpty()) {
    fileName=Message::getSaveFileName(tr("Saving parameters in log file"),
                                          tr("Log file (*.log)"));
  }
  if(fileName.length()>0) {
    QFile f(fileName);
    if(!f.open(QIODevice::WriteOnly)) {
      Message::warning(MSG_ID, tr("Saving parameters in log file"),
                       tr("Unable to open file for writing"), Message::cancel());
      return;
    }
    QTextStream s(&f);
    s << "### Parameters ###" << endl;
    AbstractParameters * param=parameters();
    if(param) {
      s << param->toString();
      delete param;
    }
    s << "### End Parameters ###" << endl;
  }
}

void AbstractToolWidget::showTool()
{
  TRACE;
  if(isMinimized()) showNormal();
  if(!isVisible()) show();
  parentWidget()->raise();
  setFocus();
}

/*!
  Prevent subpool parent widget to be closed
*/
void AbstractToolWidget::lockSubPool()
{
  TRACE;
  if(_subPoolWindow)
    _subPoolWindow->lock();
}

/*!
  Allow subpool parent widget to be closed
*/
void AbstractToolWidget::unlockSubPool()
{
  TRACE;
  if(_subPoolWindow)
    _subPoolWindow->unlock();
}

/*!
  Prevent subpool parent widget to be closed
*/
bool AbstractToolWidget::subPoolLocked()
{
  TRACE;
  if(_subPoolWindow)
    return _subPoolWindow->isLocked();
  else
    return false;
}

} // namespace GeopsyGui
