/***************************************************************************
**
**  This file is part of QGpCompatibility.
**
**  QGpCompatibility 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.
**
**  QGpCompatibility 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: 2004-09-20
**  Copyright: 2004-2019
**    Marc Wathelet
**    Marc Wathelet (ULg, Liège, Belgium)
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QGpCoreTools.h>
#include <QGpCoreWave.h>

#include "CompatRefraReport.h"
#include "CompatHodoChroneData.h"

namespace QGpCompatibility {

CompatRefraReport::CompatRefraReport(bool isWrite, QString reportFile, QString naInFile,int nModels) :
CompatInversionReport(isWrite,reportFile,naInFile,nModels)
{
  TRACE;
  _currentTiltModel=0;
  if(!isWrite) { // Force _currentDispersion to be a CompatHodoChrone
    delete _currentDispersion;
    _currentDispersion=0;
  }
}

CompatRefraReport::~CompatRefraReport()
{
  TRACE;
  delete _currentTiltModel;
}

bool CompatRefraReport::isA(const char * className)
{
  TRACE;
  return strcmp(className, "CompatRefraReport")==0;
}

void CompatRefraReport::addRefraGoal(CompatHodoChroneData * hd)
{
  TRACE;
  // tests if omegas are entered
  if(!startReadingBlock(_blockOmegas,Omegas)) {
    fprintf(stderr,"You must call addOmegas before calling addRefraGoal\n");
    return;
  }
  startWritingBlock(RefraGoal);
  if(hd) hd->dataToReport(_s);
  endWritingBlock();
}

void CompatRefraReport::modifyRefraGoal(CompatHodoChroneData * hd)
{
  TRACE;
  startWritingBlock(_blockGoal,RefraGoal);  
  if(hd) hd->dataToReport(_s);
  endWritingBlock();
}

CompatHodoChroneData * CompatRefraReport::loadRefraGoal()
{
  TRACE;
  if(!_currentDispersion) initCurrentDispersion();
  CompatHodoChroneData * rms=new CompatHodoChroneData(_currentDispersion);
  if(startReadingBlock(_blockGoal,RefraGoal)) {
    rms->reportToData(_s);
    rms->reportToDataWeight(_s,_version>=3);
  }
  else fprintf(stderr,"Unable to read block RefraGoal in current file\n");
  return rms;
}

void CompatRefraReport::loadRefra(int modelIndex)
{
  TRACE;
  if(!_currentTiltModel) initCurrentTiltModel();
  if(!_currentNAModel) _currentNAModel=new float [_nd];
  if(!_currentDispersion) initCurrentDispersion();
  if(startReadingBlock(modelIndex+_headerBlocksCount,ModelDispersion)) {
    _s >> _currentID;
    _currentModel->fromStream(_s);
    //_currentTiltModel->set(_currentModel);
    _s >> _currentCost;
    if(_version>=4) _s.readRawData((char *)_currentNAModel,_nd*sizeof(float));
    _currentDispersion->reportToValues(_s);
    if(_version>0) _currentDispersion->reportToRefines(_s);
    //_currentTiltModel->reportToSpec(_s);
  }
  else _currentCost=-1;
}

void CompatRefraReport::loadRefra(CompatHodoChrone * hodo,int modelIndex)
{
  TRACE;
  if(!_currentTiltModel) initCurrentTiltModel();
  if(!_currentNAModel) _currentNAModel=new float [_nd];
  if(!_currentDispersion) initCurrentDispersion();
  if(startReadingBlock(_blockOmegas,Omegas)) {
    hodo->reportToOmega(_s);
    if(startReadingBlock(modelIndex+_headerBlocksCount,ModelDispersion)) {
      _s >> _currentID;
      _currentModel->fromStream(_s);
      //_currentTiltModel->set(_currentModel);
      _s >> _currentCost;
      if(_version>=4) _s.readRawData((char *)_currentNAModel,_nd*sizeof(float));
      hodo->reportToValues(_s);
      if(_version>=1) hodo->reportToRefines(_s);
    }
    else _currentCost=-1;
  }
  else _currentCost=-1;
}

void CompatRefraReport::initCurrentTiltModel()
{
  TRACE;
  if(!_currentModel) initCurrentModel();  
  _currentTiltModel=new RefractionDippingModel(_currentModel->layerCount());
}

bool CompatRefraReport::initCurrentDispersion()
{
  TRACE;
  ASSERT(!_currentDispersion);
  _currentDispersion=(CompatMultiModalCurves *) new CompatHodoChrone();
  if(startReadingBlock(_blockOmegas,Omegas))
    _currentDispersion->reportToOmega(_s);
  else {
    Message::critical(MSG_ID,"Inversion report", "Bad block: Omegas at index 1",Message::cancel());
    return false;
  }
  if(_trueN>_blockEll && startReadingBlock(_blockEll,EllipticityGoal))
    if(!initCurrentEllipticity()) return false;
  if(_version<2) 
    _currentDispersion->setRayleighModesCount(_currentDispersion->modesCount());
  return true; 
}

} // namespace QGpCompatibility
