/***************************************************************************
**
**  This file is part of dinverdc.
**
**  dinverdc 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.
**
**  dinverdc 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: 2005-10-31
**  Copyright: 2005-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <DinverDCCore.h>
#include <QGpCoreTools.h>
#include "ParamProfileWidget.h"

#include <QRadioButton>
#include <QComboBox>

#include "ParamLayerWidget.h"
#include "ParamGroundModelWidget.h"

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

  _frameLayout=new QVBoxLayout(frame);
  _frameLayout->setSpacing(1);
  _frameLayout->setMargin(1);
  // signals and slots connections
  connect(addLayerBut, SIGNAL(clicked()), this, SLOT(addLayer()));
  connect(delLayerBut, SIGNAL(clicked()), this, SLOT(deleteLayer()));
  connect(this, SIGNAL(updateSize()), parent, SLOT(updateSize()));
  _nLayers=0;
  _type=ParamProfile::Param;
  _defaultCondition=SimpleCondition::LessThan;
  _groundModel=parent;
}

/*
 *  Destroys the object and frees any allocated resources
 */
ParamProfileWidget::~ParamProfileWidget()
{
  TRACE;
  // no need to delete child widgets, Qt does it all for us
}

void ParamProfileWidget::setParam(QString shortName, QString longName, QString unit,
                                  double defaultMinimum, double defaultMaximum,
                                  ParamProfile::Type type, SimpleCondition::Type defaultCondition)
{
  TRACE;
  _shortName=shortName;
  _longName=longName;
  _unit=unit;
  _defaultMinimum=defaultMinimum;
  _defaultMaximum=defaultMaximum;
  QString tstr;
  if(_unit.isEmpty()) {
    tstr=_longName;
  } else {
    tstr=_longName+" ("+_unit+")";
  }
  tstr+="\n";
  switch(type) {
  case ParamProfile::Param:
    tstr+=tr("(Parameters)");
    break;
  case ParamProfile::Condition:
    tstr+=tr("(Conditions)");
    break;
  }
  title->setText(tstr);
  _type=type;
  _defaultCondition=defaultCondition;
}

ParamLayerWidget * ParamProfileWidget::layer(int index) const
{
  return qobject_cast<ParamLayerWidget *>(_frameLayout->itemAt(index)->widget());
}


ParamLayerWidget * ParamProfileWidget::addLayer()
{
  TRACE;
  int i=selectedIndex();
  ParamLayerWidget * p=createLayer();
  if(i>=0 && i<_nLayers) {
    p->setProfile(this, layer(i));
    _frameLayout->insertWidget(i, p);
  } else if(i<0) {
    p->setProfile(this, nullptr);
    _frameLayout->insertWidget(_nLayers, p);
  }
  _nLayers++;
  setLayerIndex();
  emit updateDHLinks();
  emit updateSize();
  return p;
}

ParamLayerWidget * ParamProfileWidget::createLayer()
{
  TRACE;
  ParamLayerWidget * p=new ParamLayerWidget;
  connect(p, SIGNAL(wantToBeSelected()), this, SLOT(unselectAll()) );
  connect(p, SIGNAL(updateDHLinks()), this, SIGNAL(updateDHLinks()) );
  p->selected->setChecked(true);
  p->lastParamCondition->setChecked(true);
  return p;
}

/*!
  Return all layers
*/
QList<ParamLayerWidget *> ParamProfileWidget::layers()
{
  QList<ParamLayerWidget *> objList;
  int n=_frameLayout->count();
  for(int i=0; i<n; i++) {
    objList << layer(i);
  }
  return objList;
}

/*!
  Return all layers exept the last one (bottom half space)
*/
QList<ParamLayerWidget *> ParamProfileWidget::interfaces()
{
  QList<ParamLayerWidget *> objList;
  int n=_frameLayout->count()-1;
  for(int i=0; i<n; i++) {
    objList << layer(i);
  }
  return objList;
}

void ParamProfileWidget::deleteLayer()
{
  TRACE;
  QList<ParamLayerWidget *> objList=layers();
  ASSERT(objList.count()==_nLayers);
  for(int i=0; i<_nLayers; i++) {
    ParamLayerWidget * lw=objList.at(i);
    if(lw->isSelected()) {
      delete lw;
      _nLayers--;
      setLayerIndex();
      if(i==_nLayers) {
        --i;
      } else {
        ++i;
      }
      if(_nLayers>0) {
        objList.at(i)->selected->setChecked(true);
      }
      emit updateDHLinks();
      break;
    }
  }
}

void ParamProfileWidget::deleteAllLayers()
{
  TRACE;
  QList<ParamLayerWidget *> objList=layers();
  for(int i=0;i<_nLayers;i++) {
    delete objList.at(i);
  }
  _nLayers=0;
  emit updateDHLinks();
}

void ParamProfileWidget::setLayerIndex()
{
  TRACE;
  QList<ParamLayerWidget *> objList=layers();
  for(int i=0; i<_nLayers; i++) {
    objList.at(i)->setIndex(i);
  }
}

int ParamProfileWidget::selectedIndex() const
{
  TRACE;
  int n=_frameLayout->count();
  ASSERT(_nLayers==n);
  for(int i=0; i<_nLayers; i++) {
    if(layer(i)->isSelected()) {
      return i;
    }
  }
  return -1;
}

void ParamProfileWidget::on_moveUp_clicked()
{
  TRACE;
  int i=selectedIndex();
  if(i>0) {
    ParamLayerWidget * cur=layer(i);
    i--;
    ParamLayerWidget * up=layer(i);
    ASSERT(up);
    _frameLayout->removeWidget(cur);
    _frameLayout->removeWidget(up);
    _frameLayout->insertWidget(i, up);
    _frameLayout->insertWidget(i, cur);
    int curLayer=cur->index();
    cur->setIndex(up->index());
    up->setIndex(curLayer);
  }
}

void ParamProfileWidget::on_moveDown_clicked()
{
  TRACE;
  int i=selectedIndex();
  if(i>=0 && i<_nLayers-1) {
    ParamLayerWidget * cur=layer(i);
    ParamLayerWidget * down=layer(i+1);
    ASSERT(down);
    _frameLayout->removeWidget(cur);
    _frameLayout->removeWidget(down);
    _frameLayout->insertWidget(i, cur);
    _frameLayout->insertWidget(i, down);
    int curLayer=cur->index();
    cur->setIndex(down->index());
    down->setIndex(curLayer);
  }
}

void ParamProfileWidget::unselectAll()
{
  TRACE;
  QList<ParamLayerWidget *> objList=layers();
  for(QList<ParamLayerWidget *>::iterator it=objList.begin(); it!=objList.end(); ++it) {
    (*it)->selected->setChecked(false);
  }
}

void ParamProfileWidget::setDHLinks(QList<ParamLayerWidget *> layerList)
{
  TRACE;
  QStringList links;
  for(QList<ParamLayerWidget *>::iterator it=layerList.begin(); it!=layerList.end(); ++it) {
    links.append((*it)->name());
  }
  QList<ParamLayerWidget *> objList=layers();
  for(QList<ParamLayerWidget *>::iterator it=objList.begin(); it!=objList.end(); ++it) {
    (*it)->setDHLinks(links);
  }
}

/*!
  \fn bool ParamProfileWidget::isEmpty() const
  Return true if no layers are defined
*/

/*!
  Return the profile corresponding to this profile widget. The returned profile must be manually deleted.
*/
ParamProfile * ParamProfileWidget::paramProfile()
{
  TRACE;
  ParamProfile * p=new ParamProfile(_shortName, _longName, _unit, _defaultMinimum, _defaultMaximum,
                                             _type, _defaultCondition);
  QList<ParamLayerWidget *> objList=layers();
  ParamLayer * layer=nullptr;
  for(QList<ParamLayerWidget *>::iterator it=objList.begin(); it!=objList.end();++it) {
    layer=( * it) ->paramLayer(p);
    p->addLayer(layer);
  }
  /* TODO: in my opinion useless because topDepthIndex() is still 0
  if(layer) {
    p->_raw.resize(layer->topDepthIndex()+1);
    if(p->type()==ParamProfile::Condition) p->_maxRaw.resize(layer->topDepthIndex()+1);
  }*/
  return p;
}

void ParamProfileWidget::setFrom(ParamProfile * p)
{
  TRACE;
  deleteAllLayers();
  _shortName=p->shortName();
  _longName=p->longName();
  _unit=p->unit();
  _defaultMinimum=p->defaultMinimum();
  _defaultMaximum=p->defaultMaximum();
  _defaultCondition=p->defaultCondition();
  _type=p->type();
  if(_unit.isEmpty()) {
    title->setText(_longName);
  } else {
    title->setText(_longName+" ("+_unit+")");
  }

  int n=p->nLayers();
  for(int i=0; i<n; i++ ) {
    ParamLayerWidget * layerW=createLayer();
    layerW->setProfile(this, nullptr);
    layerW->setIndex(i);
    _frameLayout->addWidget(layerW);
    layerW->setFrom(p->layer(i));
  }
  _nLayers=n;
}

void ParamProfileWidget::setLinksFrom(ParamProfile * p)
{
  TRACE;
  QList<ParamLayerWidget *> objList=layers();
  int n=objList.count();
  ASSERT(p->nLayers()==n);
  for(int i=0; i<n; i++) {
    objList.at(i)->setLinksFrom(p->layer(i));
  }
}

void ParamProfileWidget::setEditable(bool e)
{
  TRACE;
  addLayerBut->setEnabled(e);
  delLayerBut->setEnabled(e);
  moveUp->setEnabled(e);
  moveDown->setEnabled(e);
  QList<ParamLayerWidget *> objList=layers();
  for(QList<ParamLayerWidget *>::iterator it=objList.begin(); it!=objList.end(); ++it) {
    (*it)->setEditable(e);
  }
}
