/***************************************************************************
**
**  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: 2005-09-13
**  Copyright: 2005-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <GeopsyCore.h>
#include <QGpGuiTools.h>
#include "TimeRangeParameterWidget.h"

namespace GeopsyGui {

/*
 *  Constructs a TimeRangeParameterWidget as a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 */
TimeRangeParameterWidget::TimeRangeParameterWidget(QWidget *parent, Qt::WindowFlags f)
    : QWidget(parent, f)
{
  TRACE;
  setupUi(this);

  connect(from, SIGNAL(textChanged(const QString&)), this, SIGNAL(parametersChanged()));
  connect(to, SIGNAL(textChanged(const QString&)), this, SIGNAL(parametersChanged()));
  connect(referenceEdit, SIGNAL(activated(int)), this, SIGNAL(parametersChanged()));
  connect(fromType, SIGNAL(activated(int)), this, SIGNAL(parametersChanged()));
  connect(toType, SIGNAL(activated(int)), this, SIGNAL(parametersChanged()));

  connect(referenceEdit, SIGNAL(activated(int)), this, SLOT(referenceEditChanged()));
  connect(fromType, SIGNAL(activated(int)), this, SLOT(fromTypeChanged()));
  connect(toType, SIGNAL(activated(int)), this, SLOT(toTypeChanged()));

  fromType->setCurrentIndex(1);
  toType->setCurrentIndex(1);

  _pickNames=TimePick::registeredNames();
  fromType->addItems(_pickNames);
  toType->addItems(_pickNames);
}

void TimeRangeParameterWidget::updateAllFields()
{
  TRACE;
  referenceEditChanged();
  fromTypeChanged();
  toTypeChanged();
}

void TimeRangeParameterWidget::setSubPool(const SubSignalPool * subPool)
{
  TRACE;
  _subPool=subPool;
  for(int i=referenceEdit->count()-1; i>0; i--) {
    referenceEdit->removeItem(i);
  }
  if(_subPool) {
    QMap<QString,int> names=_subPool->signalNames();
    for(QMap<QString,int>::iterator it=names.begin(); it!=names.end(); it++) {
      referenceEdit->addItem(it.key());
    }
  }
}

void TimeRangeParameterWidget::updatePicks()
{
  TRACE;
  QStringList pickNames=TimePick::registeredNames();
  if(pickNames!=_pickNames) {
    _pickNames=pickNames;
    while(fromType->count()>3) {
      fromType->removeItem(3);
    }
    fromType->addItems(_pickNames);
    while(toType->count()>3) {
      toType->removeItem(3);
    }
    toType->addItems(_pickNames);
  }
  fromTypeChanged();
  toTypeChanged();
}

void TimeRangeParameterWidget::referenceEditChanged()
{
  TRACE;
  if(referenceEdit->currentIndex()==0) {
    _reference=*_subPool;
  } else {
    QString name=referenceEdit->currentText();
    _reference.removeAll();
    for(SubSignalPool::const_iterator it=_subPool->begin(); it!=_subPool->end(); it++) {
      if((*it)->nameComponent()==name) {
        _reference.addSignal(*it);
      }
    }
  }
  fromTypeChanged();
  toTypeChanged();
}

void TimeRangeParameterWidget::fromTypeChanged()
{
  TRACE;
  switch (fromType->currentIndex()) {
  case 0:
    from->setEnabled(true);
    referenceEdit->setEnabled(toType->currentIndex()!=0 && toType->currentIndex()!=2);
    break;
  case 1:
    from->setEnabled(false);
    referenceEdit->setEnabled(true);
    if(_reference.isEmpty()) {
      from->setText(_subPool->timeRange().start().toString(DateTime::defaultUserFormat));
    } else {
      from->setText(_reference.timeRange().start().toString(DateTime::defaultUserFormat));
    }
    break;
  case 2:
    from->setEnabled(true);
    referenceEdit->setEnabled(toType->currentIndex()!=0 && toType->currentIndex()!=2);
    if(toType->currentIndex()==2) {
      toType->setCurrentIndex(1);
      toTypeChanged();
    }
    break;
  default:
    if(_reference.isEmpty()) {
      from->setText(QString());
    } else {
      Signal * sig=_reference.at(0);
      DateTime t=sig->metaData<TimePick>().value(fromType->currentText());
      from->setText(t.toString(DateTime::defaultUserFormat));
    }
    from->setEnabled(false);
    referenceEdit->setEnabled(true);
    break;
  }
}

void TimeRangeParameterWidget::toTypeChanged()
{
  TRACE;
  switch (toType->currentIndex()) {
  case 0:
    to->setEnabled(true);
    referenceEdit->setEnabled(fromType->currentIndex()!=0 && fromType->currentIndex()!=2);
    break;
  case 1:
    to->setEnabled(false);
    referenceEdit->setEnabled(true);
    if(_reference.isEmpty()) {
      to->setText(_subPool->timeRange().end().toString(DateTime::defaultUserFormat));
    } else {
      to->setText(_reference.timeRange().end().toString(DateTime::defaultUserFormat));
    }
    break;
  case 2:
    to->setEnabled(true);
    referenceEdit->setEnabled(fromType->currentIndex()!=0 && fromType->currentIndex()!=2);
    if(fromType->currentIndex()==2) {
      fromType->setCurrentIndex(1);
      fromTypeChanged();
    }
    break;
  default:
    if(!_reference.isEmpty()) {
      Signal * sig=_reference.at(0);
      DateTime t=sig->metaData<TimePick>().value(toType->currentText());
      to->setText(t.toString(DateTime::defaultUserFormat));
    } else {
      to->setText(QString());
    }
    to->setEnabled(false);
    referenceEdit->setEnabled(true);
    break;
  }
}

void TimeRangeParameterWidget::getParameters(TimeRangeParameters &param) const
{
  TRACE;
  bool ok=true;
  switch(fromType->currentIndex()) {
  case 0: {
      param.setStartType(TimeRangeParameters::Absolute);
      DateTime t;
      if(t.fromString(from->text(), DateTime::defaultUserFormat)) {
        param.setStart(t);
      }
    }
    break;
  case 1:
    if(referenceEdit->currentIndex()==0) {
      param.setStartType(TimeRangeParameters::Signal);
      param.setStart(_subPool->timeRange().start());
    } else {
      param.setStartType(TimeRangeParameters::Absolute);
      param.setStart(_reference.timeRange().start());
    }
    break;
  case 2: {
      param.setStartType(TimeRangeParameters::Delta);
      double v=Number::durationToSeconds(from->text(), ok);
      if(ok) {
        param.setDeltaT(v);
      }
    }
    break;
  default:
    if(referenceEdit->currentIndex()==0) {
      param.setStartType(TimeRangeParameters::Pick);
      param.setStartPick(fromType->currentText());
      param.setStart(_subPool->firstTimePick(fromType->currentText()));
    } else {
      param.setStartType(TimeRangeParameters::Absolute);
      param.setStart(_reference.firstTimePick(fromType->currentText()));
    }
    break;
  }
  switch(toType->currentIndex()) {
  case 0: {
      param.setEndType(TimeRangeParameters::Absolute);
      DateTime t;
      if(t.fromString(to->text(), DateTime::defaultUserFormat)) {
        param.setEnd(t);
      }
    }
    break;
  case 1:
    if(referenceEdit->currentIndex()==0) {
      param.setEndType(TimeRangeParameters::Signal);
      param.setEnd(_subPool->timeRange().end());
    } else {
      param.setEndType(TimeRangeParameters::Absolute);
      param.setEnd(_reference.timeRange().end());
    }
    break;
  case 2: {
      param.setEndType(TimeRangeParameters::Delta);
      double v=Number::durationToSeconds(to->text(), ok);
      if(ok) {
        param.setDeltaT(v);
      }
    }
    break;
  default:
    if(referenceEdit->currentIndex()==0) {
      param.setEndType(TimeRangeParameters::Pick);
      param.setEndPick(toType->currentText());
      param.setEnd(_subPool->lastTimePick(toType->currentText()));
    } else {
      param.setEndType(TimeRangeParameters::Absolute);
      param.setEnd(_reference.lastTimePick(toType->currentText()));
    }
    break;
  }
  param.setReference(referenceEdit->currentText());
}

void TimeRangeParameterWidget::setParameters(const TimeRangeParameters & param)
{
  TRACE;
  switch(param.startType()) {
  case TimeRangeParameters::Absolute:
    fromType->setCurrentIndex(0);
    from->setText(param.start().toString(DateTime::defaultUserFormat));
    break;
  case TimeRangeParameters::Signal:
    fromType->setCurrentIndex(1);
    break;
  case TimeRangeParameters::Delta:
    fromType->setCurrentIndex(2);
    from->setText(QString::number(param.deltaT()));
    break;
  case TimeRangeParameters::Pick:
    if(!param.startPick().isEmpty()) {
      int index=TimePick::registeredNames().indexOf(param.startPick());
      if(index>-1) {
        fromType->setCurrentIndex(3+index);
      }
    }
    break;
  }
  switch(param.endType()) {
  case TimeRangeParameters::Absolute:
    toType->setCurrentIndex(0);
    to->setText(param.end().toString(DateTime::defaultUserFormat));
    break;
  case TimeRangeParameters::Signal:
    toType->setCurrentIndex(1);
    break;
  case TimeRangeParameters::Delta:
    toType->setCurrentIndex(2);
    to->setText(QString::number(param.deltaT()));
    break;
  case TimeRangeParameters::Pick:
    if(!param.endPick().isEmpty()) {
      int index=TimePick::registeredNames().indexOf(param.endPick());
      if(index>-1) {
        toType->setCurrentIndex(3+index);
      }
    }
    break;
  }
  referenceEdit->setCurrentText(param.reference());
}

} // namespace GeopsyGui
