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

#include <GeopsyGui.h>
#include <QGpGuiTools.h>
#include <SciFigs.h>

#include "ChronogramWindow.h"
#include "SigSelectionDnD.h"

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

  Full description of class still missing
*/

/*!
  Description of constructor still missing
*/
ChronogramWindow::ChronogramWindow(QWidget* parent)
    : SubPoolWindow(parent)
{
  TRACE;
  setObjectName("chronogram");
  QVBoxLayout * l=new QVBoxLayout(this);
  l->setMargin(1);
  AxisWindow * w=new AxisWindow(this);
  l->addWidget(w);
  w->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
  w->setObjectName("chronogram");
  setWindowIcon(QIcon(":chronogram-22x22.png"));

  _chronogramLayer=new ChronogramLayer(w);
  _chronogramLayer->setObjectName("chronogram");
  _chronogramLayer->addTrackingAction(tr("&Select"), CHRONOGRAMLAYER_TRACKING_ID,
                                      tr("Once selected, the selection can be dragged and dropped to other viewers."));

  w->xAxis()->setTitle(tr("Time"));
  w->xAxis()->setScaleType(Scale::AbsoluteTime);
  w->yAxis()->setReversedScale(true);
  w->yAxis()->setZoomEnabled(false);
  w->xAxis()->setSizeInfo(15.0);
  w->yAxis()->setSizeInfo(10.0);

  // Drag and drop to transfert signal selection
  SigSelectionDnD * sigDnD=new SigSelectionDnD(w->graphContent());
  connect(sigDnD, SIGNAL(selectionDropped(QWidget *, const SubSignalPool&)), this, SLOT(addSignals(QWidget *, const SubSignalPool&)));
  connect(sigDnD, SIGNAL(getSelection(SubSignalPool&)), this, SLOT(getSelection(SubSignalPool&)));
  connect(w->graphContent(), SIGNAL(mouseTrackingBegin()), sigDnD, SLOT(disableFilter()) );
  connect(w->graphContent(), SIGNAL(mouseTrackingEnd()), sigDnD, SLOT(enableFilter()) );

  // Restore default properties
  QSettings& reg=CoreApplication::instance()->settings();
  QString plotProperties=reg.value("ChronogramPlot").toString();
  if(!plotProperties.isEmpty()) {
    XMLSciFigs s;
    s.restoreString(plotProperties, _chronogramLayer->graphContent(), XMLSciFigs::MakeUp);
  }

  if(GeopsyCoreEngine::instance()->preferences()->restoreChronogramMakeUp() &&
      !GeopsyCoreEngine::instance()->preferences()->chronogramMakeUpFile().isEmpty()) {
    _chronogramLayer->graph()->restoreMakeUp(GeopsyCoreEngine::instance()->preferences()->chronogramMakeUpFile());
  }
}

/*!
  Description of destructor still missing
*/
ChronogramWindow::~ChronogramWindow()
{
  TRACE;
  // Save as default properties
  QSettings& reg=CoreApplication::instance()->settings();
  XMLSciFigs s;
  QString plotProperties=s.saveString(_chronogramLayer->graphContent(), XMLSciFigs::MakeUp);
  reg.setValue("ChronogramPlot", plotProperties);
}

void ChronogramWindow::setWindowTitle(QString title)
{
  TRACE;
  SubPoolWindow::setWindowTitle( "Chronogram - " + title);
}

void ChronogramWindow::subPoolUpdate()
{
  TRACE;
  AxisWindow * w=_chronogramLayer->graph();
  if(subPool().isEmpty()) {
    setWindowTitle(QString());
    return ;
  }
  chronogramLayer()->subPoolUpdate(&subPool());
  if(subPool().count()==1) {
    Signal & sig=*subPool().at(0);
    QString traceName=sig.nameComponent();
    setWindowTitle(traceName);
  } else {
    setWindowTitle(subPool().name());
  }
  w->xAxis()->setTimeReference(subPool().timeRange().start());
  updateLabels();
  setLimits();
  if(GeopsyCoreEngine::instance()->preferences()->restoreGraphicMakeUp()) {
    _chronogramLayer->graph()->restoreMakeUp(GeopsyCoreEngine::instance()->preferences()->chronogramMakeUpFile());
  }
  w->updateInternalGeometry();
  w->deepUpdate();
}

void ChronogramWindow::setLimits()
{
  TRACE;
  if(!subPool().isEmpty()) {
    AxisWindow * w=_chronogramLayer->graph();
    Rect r=_chronogramLayer->boundingRect();
    w->xAxis()->setRange(r.x1(), r.x2());
    w->yAxis()->setRange(r.y1(), r.y2());
  }
}

void ChronogramWindow::updateLabels()
{
  TRACE;
  AxisWindow * w=_chronogramLayer->graph();

  Axis& a=*w->yAxis();
  a.setReversedScale(true);
  a.setTitle( "" );
  a.setAutoTicks(false);
  a.setMajorTicks(1.0);
  a.setMinorTicks(1.0);
  a.setScaleType(Scale::Linear);
  a.removeStringLabels();

  const SubSignalPool * subPool=chronogramLayer()->subPool();
  if(!subPool || subPool->isEmpty()) return;
  int n=_chronogramLayer->hitCount()-1;
  for(int i=0; i<n; i++ ) {
    a.addStringLabel(_chronogramLayer->name(i), false);
  }
  // Update axis... while adding the last label
  a.addStringLabel(_chronogramLayer->name(n), true);
}

void ChronogramWindow::endSignalChange(Signal * sig)
{
  TRACE;
  if(subPool().isEmpty()) return;
  if(sig && subPool().contains(sig)) {
    _chronogramLayer->rangeUpdate();
  }
  setLimits();
  _chronogramLayer->graph()->deepUpdate();
  SubPoolWindow::endSignalChange(sig);
}

void ChronogramWindow::getSelection(SubSignalPool& sel)
{
  TRACE;
  sel=_chronogramLayer->selection();
  sel.setName(tr("Selected from %1").arg(subPool().name()));
  // If nothing is selected, put everything in the selection
  if(sel.isEmpty()) {
    sel=subPool();
  }
}

void ChronogramWindow::focusInEvent(QFocusEvent * e)
{
  TRACE;
  _chronogramLayer->graphContent()->setFocus(e->reason());
}

void ChronogramWindow::fastFourierTransform(DoubleSignal::SignalType st)
{
  TRACE;
  beginSignalChange();
  subPool().fastFourierTransform(st);
  endSignalChange();
}
