
#pragma once

#include <QString>
#include <QMetaType>


#include "../types.h"
#include "../msrun/msrunreader.h"
#include "../msrun/msrunid.h"
#include "../exportinmportconfig.h"
#include "../obo/obopsimodterm.h"


namespace pappso
{

class TimsMsRunReaderMs2;
typedef std::shared_ptr<TimsMsRunReaderMs2> TimsMsRunReaderMs2SPtr;

// This class is used to access mass spectrometry data files. The file being
// opened and read might contain more than one MS run. The user of this class
// might request a vector of all these MS runs (in the form of a vector of
// MsRunIdCstSPtr. Once the MsRunIdCstSPtr of interest has been located by the
// caller, the caller might then request the MsRunReaderSPtr to use to read that
// MS run's data.
class PMSPP_LIB_DECL MsFileAccessor
{
  public:
  MsFileAccessor(const QString &file_name, const QString &xml_prefix);
  MsFileAccessor(const MsFileAccessor &other);
  virtual ~MsFileAccessor();

  const QString &getFileName() const;

  /** @brief get the raw format of mz data
   */
  MsDataFormat getFileFormat() const;


  /** @brief get OboPsiModTerm corresponding to the raw format of mz data
   */
  const OboPsiModTerm getOboPsiModTermFileFormat() const;


  /** @brief get OboPsiModTerm corresponding to the nativeID format format of mz
   * data
   */
  const OboPsiModTerm &getOboPsiModTermNativeIDFormat() const;


  /** @brief get the file reader type
   */
  FileReaderType getFileReaderType() const;

  /** @brief given an mz format, explicitly set the preferred reader
   */
  void setPreferredFileReaderType(MsDataFormat format,
                                  FileReaderType reader_type);
  FileReaderType getpreferredFileReaderType(MsDataFormat format);

  std::vector<MsRunIdCstSPtr> getMsRunIds();

  void setSelectedMsRunId(MsRunIdCstSPtr ms_run_id_csp);
  MsRunIdCstSPtr getSelectedMsRunId() const;

  MsRunReaderSPtr msRunReaderSPtr(MsRunIdCstSPtr ms_run_id);
  MsRunReaderSPtr msRunReaderSPtr(std::size_t ms_run_id_index);
  MsRunReaderSPtr msRunReaderSPtrForSelectedMsRunId();

  /** @brief get an msrun reader by finding the run_id in file
   *
   * @param run_id identifier within file of the MSrun
   * @param xml_id XML identifier given by the user to identify this MSrun in
   * our experiment (not in the file)
   */
  MsRunReaderSPtr getMsRunReaderSPtrByRunId(const QString &run_id,
                                            const QString &xml_id);

  /** @brief get an MsRunReader directly from a valid MsRun ID
   *
   * no need to check the file format or filename : all is already part of the
   * msrunid
   *
   * @param ms_run_id msrun identifier
   * @return msrun reader shared pointer
   */
  static MsRunReaderSPtr buildMsRunReaderSPtr(MsRunIdCstSPtr ms_run_id);

  /** @brief get an MsRunReader directly from a valid MsRun ID
   *
   * no need to check the file format or filename : all is already part of the
   * msrunid
   *
   * @param ms_run_id msrun identifier
   * @param preferred_file_reader_type the preferred file reader type to use
   * (depending on the mz format)
   * @return msrun reader shared pointer
   */
  static MsRunReaderSPtr
  buildMsRunReaderSPtr(MsRunIdCstSPtr ms_run_id,
                       pappso::FileReaderType preferred_file_reader_type);

  /** @brief if possible, builds directly a dedicated Tims TOF tdf file reader
   */
  TimsMsRunReaderMs2SPtr buildTimsMsRunReaderMs2SPtr();

  private:
  QString m_fileName;

  // When opening more than one file concurrently in a determinate session, we
  // need this prefix to craft unabiguous ms run ids.
  const QString m_xmlPrefix;

  MsDataFormat m_fileFormat = MsDataFormat::unknown;

  // Type of the file reader that could load the file.
  FileReaderType m_fileReaderType;

  std::map<MsDataFormat, FileReaderType> m_preferredFileReaderTypeMap;

  MsRunIdCstSPtr mcsp_selectedMsRunId = nullptr;

  OboPsiModTerm m_oboPsiModTermNativeIDFormat;
};

typedef std::shared_ptr<MsFileAccessor> MsFileAccessorSPtr;
typedef std::shared_ptr<const MsFileAccessor> MsFileAccessorCstSPtr;

} // namespace pappso
