/**
 * \file pappsomspp/vendors/tims/timsframetype1.h
 * \date 3/10/2021
 * \author Olivier Langella
 * \brief handle a single Bruker's TimsTof frame type 1 compression
 */

/*******************************************************************************
 * Copyright (c) 2021 Olivier Langella <Olivier.Langella@u-psud.fr>.
 *
 * This file is part of the PAPPSOms++ library.
 *
 *     PAPPSOms++ 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.
 *
 *     PAPPSOms++ 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 PAPPSOms++.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/

#pragma once

#include "timsframe.h"
#include "pappsomspp/export-import-config.h"

namespace pappso
{
/**
 * @todo write docs
 */
class PMSPP_LIB_DECL TimsFrameType1 : public TimsFrame
{
  public:
  /**
   * @param timsId tims frame id
   * @param scanNum total number of scans in this frame
   * @param p_bytes pointer on the decompressed binary buffer
   * @param len size of the decompressed binary buffer
   */
  TimsFrameType1(std::size_t timsId,
                 quint32 scanNum,
                 char *p_bytes,
                 std::size_t len);

  /**
   * Copy constructor
   *
   * @param other TODO
   */
  TimsFrameType1(const TimsFrameType1 &other);

  /**
   * Destructor
   */
  virtual ~TimsFrameType1();


  virtual std::size_t getScanPeakCount(std::size_t scanNum) const override;


  /** @brief get raw index list for one given scan
   * index are not TOF nor m/z, just index on digitizer
   */
  virtual std::vector<quint32>
  getScanTofIndexList(std::size_t scanNum) const override;

  /** @brief get raw intensities without transformation from one scan
   * it needs intensity normalization
   */
  virtual std::vector<quint32>
  getScanIntensityList(std::size_t scanNum) const override;

  /** @brief get the mass spectrum corresponding to a scan number
   * @param scanNum the scan number to retrieve
   * */

  virtual pappso::MassSpectrumSPtr
  getMassSpectrumSPtr(std::size_t scanNum) const override;


  protected:
  /** @brief cumulate a scan into a map
   *
   * @param scanNum scan number 0 to (m_scanNumber-1)
   */
  virtual void cumulateScan(std::size_t scanNum,
                            TimsDataFastMap &accumulate_into) const override;

  virtual void
  cumulateScan2(std::size_t scanNum,
                TimsDataFastMap &accumulate_into,
                quint32 accepted_tof_index_range_begin,
                quint32 accepted_tof_index_range_end) const override;

  /** @brief get the raw index tof_index and intensities (normalized)
   *
   * @param scanNum the scan number to extract
   * @return trace vector
   *
   */
  virtual pappso::TraceSPtr getRawTraceSPtr(std::size_t scanNum) const override;


  /** @brief get the raw index tof_index and intensities (normalized)
   *
   * @param scanNum the scan number to extract
   * @param accepted_tof_index_range_begin mz index begin
   * @param accepted_tof_index_range_end mz index end
   * @return vector of RawValuePair
   *
   */
  virtual std::vector<TofIndexIntensityPair>
  getRawValuePairList(std::size_t scanNum,
                      quint32 accepted_tof_index_range_begin,
                      quint32 accepted_tof_index_range_end) const override;

  private:
  /** @brief copy buffer header and lzf decompress each scan for tims
   * compression type 1
   * @param src raw data buffer containing scan offsets and LZF compressed scans
   * @param len length of the data buffer
   */
  void copyAndLzfDecompress(const char *src, std::size_t len);

  /** @brief decompress a single LZF compressed scan buffer
   * @param src pointer on the LZF compressed buffer
   * @param src_len length of the source buffer
   * @param dest pointer to the destination buffer (in the qbyte array)
   * @param dest_len length of the destination buffer (max possible in the
   * qbytearray)
   * @return scan decompressed size
   */
  unsigned int lzfDecompressScan(const char *src,
                                 unsigned int src_len,
                                 char *dest,
                                 unsigned int dest_len);

  private:
  std::vector<std::size_t> m_scanOffsetList;
  std::vector<std::size_t> m_scanSizeList;
};
} // namespace pappso
