/***************************************************************************
**
**  This file is part of gpmaplayer.
**
**  gpmaplayer 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.
**
**  gpmaplayer 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: 2016-03-27
**  Copyright: 2016-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#include "ColumnImageMerger.h"

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

  Full description of class still missing
*/

/*!
  Description of constructor still missing
*/
ColumnImageMerger::ColumnImageMerger(double lon, double minLat, double maxLat, double step)
  : ImageMerger()
{
  TRACE;
  for(double lat=minLat; lat<=maxLat; lat+=step) {
    _centers.append(Point2D(lon, lat));
  }
  if(_centers.isEmpty()) {
    _centers.append(Point2D(lon, minLat));
  }
  _currentIndex=0;
}

/*!
  Description of destructor still missing
*/
ColumnImageMerger::~ColumnImageMerger()
{
  TRACE;
}

void ColumnImageMerger::setImage(const QImage& im, int minShift, int maxShift)
{
  TRACE;
  const Point2D& c=_centers.at(_currentIndex);
  App::log(tr("  Processing image centered at %1, %2\n").arg(c.x(), 9, 'f', 5, ' ').arg(c.y(), 9, 'f', 5, ' ') );
  if(_image.isNull()) {
    _image=im;
  } else {
    int s;
    if(ImageMerger::forcedYStep()>0.0) {
      s=ImageMerger::forcedYStep();
    } else {
      bool ok;
      s=getPixelShift(im, _image, minShift, maxShift, ok);
      if(!ok) {
        App::log(tr("  No correlation between successive images, check latitude step\n") );
        if(isDebugMode()) {
          QString fileName=QString("gpmaplayer_debug_col_%1_%2-%3.png").arg(c.x(), 10, 'f', 5, '_').arg(c.y(), 10, 'f', 5, '_');
          im.save(fileName.arg(1), "PNG");
          App::log(tr("New image  saved in '%1'\n").arg(fileName.arg(1)) );
          _image.save(fileName.arg(2), "PNG");
          App::log(tr("Main image  saved in '%1'\n").arg(fileName.arg(2)) );
        }
        printAverageSteps();
        ::exit(2);
      }
    }
    QImage newIm(_image.size()+QSize(0, s), _image.format());
    QPainter p;
    p.begin(&newIm);
    p.drawImage(0, 0, im);
    p.drawImage(0, s, _image);
    p.end();
    _image=newIm;
  }
  _currentIndex++;
}

int ColumnImageMerger::getPixelShift(const QImage& im1, const QImage& im2, int minShift, int maxShift, bool& ok)
{
  TRACE;
  // New image is above the current main image
  // For correlation we just scan the top ot the main image
  DoubleSignal * newVector=imageVector(im1, im1.height());
  DoubleSignal * mainVector=imageVector(im2, im1.height());
  DoubleSignal * corr=new DoubleSignal();
  corr->normalizedCorrelation(mainVector, newVector, mainVector->nSamples()-1);
  int n=(corr->nSamples()-1)/2;
  int s=corr->maximumAt(n+minShift, n+maxShift);
  double sv=corr->amplitudeAt(s);
  s-=(corr->nSamples()-1)/2;
  App::log(tr("  Best correlation at %1 (value=%2)\n").arg(s).arg(sv) );

  if(sv<0.80) {
    s=defaultYStep();
    if(s>0.0) {
      App::log(tr("  Using default step %1\n").arg(s) );
      ok=true;
    } else {
      if(isDebugMode()) {
        exportDebugSignals(newVector, mainVector, corr);
      }
      ok=false;
      App::log(tr("  No default step yet available, specify a fake default Y step.\n"
                          "  At the end note the average Y step and re-run with a better default step.\n"));
    }
  } else {
    addGoodYStep(s);
    ok=true;
  }
  delete newVector;
  delete mainVector;
  delete corr;
  return s;
}

DoubleSignal * ColumnImageMerger::imageVector(const QImage& im, int maxHeight)
{
  TRACE;
  const QRgb * m=reinterpret_cast<const QRgb *>(im.constBits());
  int w=im.width();
  int h=im.height();
  if(h>maxHeight) {
    h=maxHeight;
  }
  DoubleSignal * v=new DoubleSignal(h);
  v->setSamplingPeriod(1.0); // Useless here, just to avoid errors in GeopsyCore
  LOCK_SAMPLES(double, vSamples, v)
    for(int i=0; i<h; i++) {
      double sum=0.0;
      for(int j=0; j<w; j++) {
        Color c(m[j]);
        c.toGray();
        sum+=c.red();
      }
      vSamples[i]=sum/w;
      m+=w;
    }
  UNLOCK_SAMPLES(v)
  DoubleSignal * vP=preprocess(v);
  delete v;
  return vP;
}
