/***************************************************************************
**
**  This file is part of DinverCore.
**
**  DinverCore 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.
**
**  DinverCore 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-05-13
**  Copyright: 2009-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#ifndef MODELSET_H
#define MODELSET_H

#include <QGpCoreTools.h>

namespace DinverCore {

class Model;
class RealSpace;
class ReportReader;

class ModelSet : private QSet<Model>, private IncreaseStorage
{
  TRANSLATIONS("ModelSet")
public:
  ModelSet(int parameterCount, int targetCount, int defaultCapacity=16384);
  ~ModelSet();

  bool importModelsFromAscii(RealSpace& parameterSpace, QString fileName);
  bool importModelsFromReport(RealSpace& parameterSpace, ReportReader& report, bool strict=true);
  bool importModels(RealSpace& parameterSpace, QString fileName, bool strict=true);
  int add(const RealSpace& parameterSpace, const double * misfit=0);

  inline void setMisfit(int modelIndex, int targetIndex, double m);
  //void setVolume(int modelIndex, double v) {_volumes[modelIndex]=v;}
  void clear();

  void reserve(int n) {IncreaseStorage::reserve(n);}
  int count() const {return _highestValidIndex+1;}
  int parameterCount() const {return _parameterCount;}
  int targetCount() const {return _targetCount;}

  const int * model(int modelIndex) const {return _parameters+_parameterCount*modelIndex;}
  const int * firstModel() const {return _parameters;}
  const double * misfit(int modelIndex) const {return _misfits+_targetCount*modelIndex;}
  //double volume(int modelIndex) const {return _volumes[modelIndex];}

  void lock() {_modelLock.lockForRead();}
  void unlock() {_modelLock.unlock();}

  void print(const int * model) const;
  void print(int modelIndex) const;
  int bestModel() const;
private:
  virtual void reallocate();

  int _parameterCount;
  int _targetCount;
  int _highestValidIndex;
  int * _parameters;
  double * _misfits;
  //double * _volumes;

  Mutex _setLock;
  ReadWriteLock _modelLock;
};

  inline void ModelSet::setMisfit(int modelIndex, int targetIndex, double m)
  {
    _misfits[_targetCount*modelIndex+targetIndex]=m;
    if(modelIndex>_highestValidIndex) {
      _highestValidIndex=modelIndex;
    }
  }

} // namespace DinverCore

#endif // MODELSET_H
