/***************************************************************************
**
**  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 <qvariant.h>
#include <QScrollArea>
#include <QHBoxLayout>

#include <DinverCore.h>
#include <DinverDCCore.h>
#include <DinverGui.h>
#include <QGpCoreTools.h>
#include <QGpGuiTools.h>
#include "ParamGroundModelWidget.h"
#include "ParamGroundModelWidget.h"
#include "ParamLayerWidget.h"
#include "ParamProfileWidget.h"

/*
 *  Constructs a ParamGroundModelWidget as a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 */
ParamGroundModelWidget::ParamGroundModelWidget(QWidget *parent, Qt::WindowFlags f)
    : QWidget(parent, f)
{
  TRACE;
  vboxLayout=new QVBoxLayout(this);
  vboxLayout->setSpacing(6);
  vboxLayout->setMargin(0);

  modelSheet=new QScrollArea;
  vboxLayout->addWidget(modelSheet);

  QWidget * modelSheetArea=new QWidget;
  QLayout * layout=new QVBoxLayout(modelSheetArea);
  profileGeometry=new QSplitter(modelSheetArea);
  layout->addWidget(profileGeometry);
  modelSheet->setWidget(modelSheetArea);

  // Add custom condition editor
  QWidget * ccw=new QWidget(this);
  QVBoxLayout * ccLayout=new QVBoxLayout(ccw);
  ccLayout->setSpacing(6);
  ccLayout->setMargin(0);

  QLabel * label=new QLabel(this);
  QFont font;
  font.setBold(true);
  font.setWeight(75);
  label->setFont(font);
  label->setTextFormat(Qt::PlainText);
  label->setAlignment(Qt::AlignCenter);
  label->setText(tr("Custom conditions"));
  ccLayout->addWidget(label);

  customConditions=new ParamSpaceEditor(this);
  customConditions->setObjectName(QString::fromUtf8("customConditions"));
  customConditions->setFrom("// linear(\"TopVs1\",\">\",1.2,\"BottomVs0\",1000);\n"
                            "// which means: TopVs1>1.2*BottomVs0+1000");
  connect(customConditions, SIGNAL(check()), this, SLOT(checkCustomConditions()));
  ccLayout->addWidget(customConditions);

  profileGeometry->addWidget(ccw);
}

/*
 *  Destroys the object and frees any allocated resources
 */
ParamGroundModelWidget::~ParamGroundModelWidget()
{
  TRACE;
}

ParamProfileWidget * ParamGroundModelWidget::newProfile()
{
  TRACE;
  ParamProfileWidget * w=new ParamProfileWidget(this);
  profileGeometry->insertWidget(profileGeometry->count()-1, w);
  connect(w, SIGNAL(updateDHLinks()), this, SLOT(setDHLinks()));
  updateSize();
  w->show();
  return w;
}

void ParamGroundModelWidget::updateSize()
{
  TRACE;
  profileGeometry->parentWidget()->adjustSize();
}

void ParamGroundModelWidget::setDHLinks()
{
  TRACE;
  QList<ParamProfileWidget *> objList=modelSheet->widget() ->findChildren<ParamProfileWidget *>();
  for(QList<ParamProfileWidget *>::iterator it=objList.begin();it!=objList.end();++it) {
    QList<ParamLayerWidget *> layerList;
    ParamProfileWidget * p=*it;
    for(QList<ParamProfileWidget *>::iterator it=objList.begin();it!=objList.end();++it) {
      if(*it!=p) {
        layerList << (*it) ->interfaces();
      }
    }
    p->setDHLinks(layerList);
  }
}

void ParamGroundModelWidget::setFrom(ParamGroundModel * gm)
{
  TRACE;
  int nProfiles=gm->nProfiles();
  ParamProfile * p;
  ParamProfileWidget * profileW;
  for(int i=0; i<nProfiles; i++) {
    p=gm->profile(i);
    profileW=find(p->shortName());
    if(!profileW) {
      profileW=newProfile();
    }
    profileW->setFrom(p);
  }
  setDHLinks();
  for(int i=0; i<nProfiles; i++) {
    p=gm->profile(i);
    profileW=find(p->shortName());
    ASSERT(profileW);
    profileW->setLayerIndex();
    profileW->setLinksFrom(p);
  }
  customConditions->setFrom(&gm->customConditions());
  // Noticed with Qt 5.7.1 that size is not correctly updated
  // with processEvents() without argument. I don't know why.
  QApplication::processEvents(QEventLoop::AllEvents, 10000);
  updateSize();
}

ParamGroundModel * ParamGroundModelWidget::paramGroundModel()
{
  TRACE;
  ParamGroundModel * gm=new ParamGroundModel;
  QList<ParamProfileWidget *> objList=modelSheet->widget() ->findChildren<ParamProfileWidget *>();
  for(QList<ParamProfileWidget *>::iterator it=objList.begin();it!=objList.end();++it) {
    gm->addProfile(( *it) ->paramProfile());
  }
  gm->setCustomConditions(customConditions->text());
  return gm;
}

ParamProfileWidget * ParamGroundModelWidget::find(QString shortName)
{
  TRACE;
  QList<ParamProfileWidget *> objList=modelSheet->widget() ->findChildren<ParamProfileWidget *>();
  QList<ParamProfileWidget *>::iterator it;
  for(it=objList.begin();it!=objList.end();++it) {
    if(( *it) ->shortName()==shortName) break;
  }
  if(it!=objList.end()) {
    return * it;
  } else {
    return nullptr;
  }
}


void ParamGroundModelWidget::clear()
{
  TRACE;
  QList<ParamProfileWidget *> wList=findChildren<ParamProfileWidget *>();
  qDeleteAll(wList);
}

void ParamGroundModelWidget::save()
{
  TRACE;
  save(QString());
}

void ParamGroundModelWidget::save(QString fileName)
{
  TRACE;
  if(fileName.isEmpty()) {
    fileName=Message::getSaveFileName(tr("Save parameterization"),
                                      tr("Dinver parameters (*.param)"),
                                      QString());
  }
  if(fileName.length() > 0) {
    ParamGroundModel * p=paramGroundModel();
    XMLVirtualPlugin plugin(p, "DispersionCurve");
    XMLDinverHeader hdr(&plugin);
    if(hdr.xml_saveFile(fileName)==XMLClass::ErrorFileNotOpen) {
      Message::warning(MSG_ID, tr("Saving parameters"), tr("Cannot open file for writing"), Message::cancel(), true);
    }
    delete p;
  }
}

void ParamGroundModelWidget::load()
{
  TRACE;
  load(QString());
}

void ParamGroundModelWidget::load(QString fileName)
{
  TRACE;
  if(fileName.isEmpty()) {
    fileName=Message::getOpenFileName(tr("Load parameterization"),
                                      tr("Dinver parameters (*.param);;"
                                         "Dinver environment (*.dinver)"));
  }
  if(fileName.length() > 0) {
    ParamGroundModel p;
    XMLVirtualPlugin plugin(&p, "DispersionCurve");
    XMLDinverHeader hdr(&plugin);
    if(hdr.xml_restoreFile(fileName)==XMLClass::NoError) {
      setFrom(&p);
    } else {
      Message::warning(MSG_ID, tr("Loading parameters"), tr("Error parsing file"), Message::cancel(), true);
    }
  }
}

void ParamGroundModelWidget::showEvent(QShowEvent * )
{
  TRACE;
  updateSize();
}

void ParamGroundModelWidget::setEditable(bool e)
{
  TRACE;
  QList<ParamProfileWidget *> objList=modelSheet->widget() ->findChildren<ParamProfileWidget *>();
  for(QList<ParamProfileWidget *>::iterator it=objList.begin();it!=objList.end();++it) {
    (*it)->setEditable(e);
  }
}

void ParamGroundModelWidget::checkCustomConditions()
{
  TRACE;
  ParamSpaceScript * s=customConditions->script();
  ParamGroundModel * gm=paramGroundModel();
  RealSpace t;
  gm->toParameters(t);
  if(s->apply(&t) ) {
    t.humanInfo();
  }
  delete s;
  delete gm;
}
