/***************************************************************************
**
**  This file is part of QGpCoreWave.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file 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 Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2006-09-26
**  Copyright: 2006-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QGpCoreTools.h>
#include "ModalFactory.h"
#include "ModalStorage.h"
#include "ModalCurve.h"

namespace QGpCoreWave {

/*!
  \class ModalFactory ModalFactory.h
  \brief Gathers ModalStorage to compute misfit for Rayleigh/Love and Phase/Group slowness

  Initialized is achieved with three distinct steps:

  \li 1.a. Repeated calls to setX() to build a list gathering all X of the curves
  \li 1.b. Repeated calls to linkX() to link points of the curves to X list indexes
  \li 2.   Repeated calls to setModes() to set the number of modes according to curves needs.
  \li 3.   Switch to angular frequency

  Never mix these steps.
*/

/*!
  \fn ModalFactory::validate()=0
  After setting omegas, you can adjust the number of modes between various storages.
  e.g. if group slowness is present force storage phase (necessary step for computing
  group slowness).
*/

/*!
  \fn ModalFactory::calculate()=0
  Fill in the modal storages by calculating theoretical
*/

/*!
  Merge x vectors of the two factories
*/
void ModalFactory::setX (ModalFactory& f)
{
  TRACE;
  _x.reserve(_x.count()+f._x.count());
  for(QVector<double>::Iterator it=f._x.begin(); it!=f._x.end(); it++ ) {
    _x.append( *it);
  }
  std::sort(_x.begin(), _x.end());
  unique(_x);
  f._x=_x;
}

/*!
  Repeat calls to setX()
*/
void ModalFactory::setX (const QList<ModalCurve>& curves)
{
  TRACE;
  for(QList<ModalCurve>::const_iterator it=curves.begin();it!=curves.end();++it) {
    setX(*it);
  }
}

/*!
  Repeat calls to linkX()
*/
void ModalFactory::linkX (QList<ModalCurve>& curves) const
{
  TRACE;
  for(QList<ModalCurve>::iterator it=curves.begin();it!=curves.end();++it) {
    linkX(*it);
  }
}

/*!
  Repeat calls to setModes()
*/
void ModalFactory::setModes (const QList<ModalCurve>& curves)
{
  TRACE;
  for(QList<ModalCurve>::const_iterator it=curves.begin();it!=curves.end();++it) {
    setModes(*it);
  }
}

/*!
  Must be called before setModes()
*/
void ModalFactory::setX (const ModalCurve& c)
{
  TRACE;
  _x.reserve(_x.count()+c.count());
  for(ModalCurve::const_iterator it=c.begin(); it!=c.end(); it++ ) {
    _x.append(it->x());
  }
  std::sort(_x.begin(), _x.end());
  unique(_x);
}

/*!
  Must be called before setModes()
*/
void ModalFactory::linkX (ModalCurve& c) const
{
  TRACE;
  if(_x.isEmpty()) {
    App::log(tr("### ERROR ### : omega list not set or empty when linking omegas.\n") );
    return;
  }
  c.linkX(_x);
}

void ModalFactory::setModes(const ModalCurve& c)
{
  TRACE;
  if(_x.isEmpty()) {
    App::log(tr("### ERROR ### : X list not set or empty when setting modes.\n") );
    return;
  }
  const QList<Mode>& l=c.modes();
  for(QList<Mode>::ConstIterator it=l.begin(); it!=l.end(); it++ ) {
    setMode(*it);
  }
}

/*!
  Switch to omega from frequency. Must be called only once.
*/
void ModalFactory::setAngularFrequency()
{
  TRACE;
  double factor=2*M_PI;
  for(QVector<double>::iterator it=_x.begin(); it!=_x.end(); it++ ) {
    (*it)*=factor;
  }
}

} // namespace QGpCoreWave
