/* BEGIN software license
 *
 * msXpertSuite - mass spectrometry software suite
 * -----------------------------------------------
 * Copyright (C) 2009--2020 Filippo Rusconi
 *
 * http://www.msxpertsuite.org
 *
 * This file is part of the msXpertSuite project.
 *
 * The msXpertSuite project is the successor of the massXpert project. This
 * project now includes various independent modules:
 *
 * - massXpert, model polymer chemistries and simulate mass spectrometric data;
 * - mineXpert, a powerful TIC chromatogram/mass spectrum viewer/miner;
 *
 * This program 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.
 *
 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * END software license
 */


#include <QIODevice>
#include <QDebug>

#include "DiscoveriesPreferences.hpp"

namespace MsXpS
{
namespace MineXpert
{


//! Construct an DiscoveriesPreferences instance
/*!

  A number of \c m_dataFormatStringSpecifHash items are created, namely the
  "TIC chrom.", the "Mass Spec." and "Drift spec." data format labels
  corresponding respectively to FormatType::TIC_CHROM, FormatType::MASS_SPEC
  and FormatType::DRIFT_SPEC.

*/
DiscoveriesPreferences::DiscoveriesPreferences()
{
  // Initialize the format string hash with the labels. We do not know yet the
  // format strings defined by the user.

  DataFormatStringSpecif *specif = new DataFormatStringSpecif;
  specif->m_formatType           = FormatType::TIC_CHROM;
  specif->m_label                = "TIC chrom.";
  specif->m_format               = "";
  m_dataFormatStringSpecifHash.insert(FormatType::TIC_CHROM, specif);

  specif               = new DataFormatStringSpecif;
  specif->m_formatType = FormatType::MASS_SPEC;
  specif->m_label      = "Mass Spec.";
  specif->m_format     = "";
  m_dataFormatStringSpecifHash.insert(FormatType::MASS_SPEC, specif);

  specif               = new DataFormatStringSpecif;
  specif->m_formatType = FormatType::DRIFT_SPEC;
  specif->m_label      = "Drift Spec.";
  specif->m_format     = "";
  m_dataFormatStringSpecifHash.insert(FormatType::DRIFT_SPEC, specif);

  // Sanity check just to make sur we understand what we do, in particular
  // because this format list is going to be used in the analysis
  // preferences dialog window, and we need to be sure that there is a
  // format type string for each element in the FormatType enum, less the
  // LAST one.
  if(m_dataFormatStringSpecifHash.size() != FormatType::LAST)
    qFatal() << "Programming error.";
}

//! Construct an initialized DataDiscoveriesPreferences instance
/*!

  \param other DataDiscoveriesPreferences instance to use for the initialization of
  \c this instance.

*/
DiscoveriesPreferences::DiscoveriesPreferences(const DiscoveriesPreferences &other)
  : m_fileName(other.m_fileName),
    m_sampleName(other.m_sampleName),
    m_recordTarget(other.m_recordTarget),
    m_fileOpenMode(other.m_fileOpenMode)
{
  // Now duplicate the other's hash that links the FormatType and the
  // DataFormatStringSpecif allocated instance.

  QList<DataFormatStringSpecif *> list =
    other.m_dataFormatStringSpecifHash.values();

  for(int iter = 0; iter < list.size(); ++iter)
    {
      DataFormatStringSpecif *specif = list.at(iter);

      DataFormatStringSpecif *newSpecif = new DataFormatStringSpecif;

      newSpecif->m_formatType = specif->m_formatType;
      newSpecif->m_label      = specif->m_label;
      newSpecif->m_format     = specif->m_format;

      m_dataFormatStringSpecifHash.insert(newSpecif->m_formatType, newSpecif);
    }

  // Sanity check just to make sur we understand what we do, in particular
  // because this format list is going to be used in the analysis
  // preferences dialog window, and we need to be sure that there is a
  // format type string for each element in the FormatType enum, less the
  // LAST one.

  if(m_dataFormatStringSpecifHash.size() != FormatType::LAST)
    qFatal() << "Programming error.";
}

//! Destruct this DiscoveriesPreferences instance.
DiscoveriesPreferences::~DiscoveriesPreferences()
{
  // We need to free all the DataFormatStringSpecif instances.
  QList<DataFormatStringSpecif *> list = m_dataFormatStringSpecifHash.values();

  for(int iter = 0; iter < list.size(); ++iter)
    {
      DataFormatStringSpecif *specif = list.at(iter);

      delete specif;
    }
}

DiscoveriesPreferences &
DiscoveriesPreferences::initialize(const DiscoveriesPreferences &other)
{
  if(this == &other)
    return *this;

  m_fileName     = other.m_fileName;
  m_sampleName   = other.m_sampleName;
  m_recordTarget = other.m_recordTarget;
  m_fileOpenMode = other.m_fileOpenMode;

  QList<DataFormatStringSpecif *> list =
    other.m_dataFormatStringSpecifHash.values();

  for(int iter = 0; iter < list.size(); ++iter)
    {
      DataFormatStringSpecif *specif = list.at(iter);

      DataFormatStringSpecif *newSpecif = new DataFormatStringSpecif;

      newSpecif->m_formatType = specif->m_formatType;
      newSpecif->m_label      = specif->m_label;
      newSpecif->m_format     = specif->m_format;

      m_dataFormatStringSpecifHash.insert(newSpecif->m_formatType, newSpecif);
    }

  // Sanity check just to make sur we understand what we do, in particular
  // because this format list is going to be used in the analysis
  // preferences dialog window, and we need to be sure that there is a
  // format type string for each element in the FormatType enum, less the
  // LAST one.

  if(m_dataFormatStringSpecifHash.size() != FormatType::LAST)
    qFatal() << "Programming error.";

  return *this;
}

//! Assignment operator
/*!

  Performs a deep copy of the \p other instance data into \c this intance.

  \param other reference to another AnalyisPreferences instance to use for the
  assignment.

  \return a reference to \c this instance.

*/
DiscoveriesPreferences &
DiscoveriesPreferences::operator=(const DiscoveriesPreferences &other)
{
  if(&other == this)
    return *this;

  m_fileName     = other.m_fileName;
  m_sampleName   = other.m_sampleName;
  m_recordTarget = other.m_recordTarget;
  m_fileOpenMode = other.m_fileOpenMode;

  QList<DataFormatStringSpecif *> list =
    other.m_dataFormatStringSpecifHash.values();

  for(int iter = 0; iter < list.size(); ++iter)
    {
      DataFormatStringSpecif *specif = list.at(iter);

      DataFormatStringSpecif *newSpecif = new DataFormatStringSpecif;

      newSpecif->m_formatType = specif->m_formatType;
      newSpecif->m_label      = specif->m_label;
      newSpecif->m_format     = specif->m_format;

      m_dataFormatStringSpecifHash.insert(newSpecif->m_formatType, newSpecif);
    }

  // Sanity check just to make sur we understand what we do, in particular
  // because this format list is going to be used in the analysis
  // preferences dialog window, and we need to be sure that there is a
  // format type string for each element in the FormatType enum, less the
  // LAST one.

  if(m_dataFormatStringSpecifHash.size() != FormatType::LAST)
    qFatal() << "Programming error.";

  return *this;
}

//! Creates a string describing \c this DiscoveriesPreferences instance
/*!

  \return A string describing \c this DiscoveriesPreferences instance

*/
QString
DiscoveriesPreferences::toString() const
{
  QString text;

  text += m_recordTarget & RECORD_TO_CONSOLE ? "Record to console\n" : "";
  text += m_recordTarget & RECORD_TO_FILE ? "Record to file\n" : "";

  if(m_fileOpenMode == QIODevice::Truncate)
    text += "File open mode: overwrite \n";
  else
    text += "File open mode: append \n";

  QList<DataFormatStringSpecif *> list = m_dataFormatStringSpecifHash.values();

  // Sanity check.
  if(list.size() != FormatType::LAST)
    qFatal() << "Programming error.";

  for(int iter = 0; iter < list.size(); ++iter)
    {
      DataFormatStringSpecif *specif = list.at(iter);

      text += QString("%1 :\n%2\n").arg(specif->m_label).arg(specif->m_format);
    }

  return text;
}


} // namespace MineXpert

} // namespace MsXpS
