/**
 * \file pappsomspp/processing/spectree/bucketclustering.h
 * \date 13/12/2023
 * \author Olivier Langella
 * \brief rearrange itemcarts into buckets
 *
 * C++ implementation of algorithm already described in :
 * 1. David, M., Fertin, G., Rogniaux, H. & Tessier, D. SpecOMS: A Full Open
 * Modification Search Method Performing All-to-All Spectra Comparisons within
 * Minutes. J. Proteome Res. 16, 3030–3038 (2017).
 *
 * https://www.theses.fr/2019NANT4092
 */


/*
 * SpecTree
 * Copyright (C) 2023  Olivier Langella
 * <olivier.langella@universite-paris-saclay.fr>
 *
 * This program is free software: you can redistribute ipetide to spectrum
 * alignmentt 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 th^e GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#pragma once

#include "itemcart.h"
#include "bucket.h"
#include <map>

namespace pappso
{
namespace spectree
{

/***
 * Implements a collection of lexicographically sortable buckets (according to
 * the positive integer identifiers they contain).
 *
 * @author Matthieu David
 * @version 0.1
 */

class PMSPP_LIB_DECL BucketClustering
{
  public:
  /**
   * Initializes and fill the map collection containing the buckets and their
   * content (spectra identifiers). The spectra identifiers and masses sets are
   * read from Spectrum objects.
   * @param spectra an array of Spectrum
   * @return a map of integers to buckets
   */
  BucketClustering();


  /** @brief add ItemCart to Bucket list
   * Each item in the cart is a key to build dedicated buckets for one item
   * The buckets will then reference the carts that contains one item
   *
   * @param item_cart to add in the bucket list
   */
  void addItemCart(const ItemCart &item_cart);

  std::size_t getItemCartCount() const;

  /**
   * Iterate the buckets present in the map collection and store them into a raw
   * array of buckets lexicographically sorted based on the buckets content.
   * Erase the map representation afterwards to spare memory.
   * @return an array of buckets
   * @since 0.1
   */
  std::vector<Bucket> asSortedList() const;

  /**
   * Provides access to the number of buckets present in the collection.
   * @return The size of the collection
   * @since 0.1
   */
  std::size_t size() const;


  /** @brief removes buckets only showing intra relations in the spectrum index
   * range
   *
   * removes buckets if their relationships implies only spectrum within the
   * range of index given as arguments
   *
   * @remark as spectrum index are sorted in buckets, boundaries are easy to
   * check
   *
   * @param spectrum_idx_begin spectrum index defining the starting boundary
   * @param spectrum_idx_end spectrum index defining the ending boundary
   *
   */
  void removeBucketsWithinCartIdRange(std::size_t spectrum_idx_begin,
                                      std::size_t spectrum_idx_end);


  private:
  /**
   * Map of the mass value to the bucket representing this mass value.
   * This representation is mainly used to fill the data and is then stored into
   * a raw array and disposed.
   * @since 0.1
   */
  std::map<std::size_t, Bucket> m_bucketMap;

  std::size_t m_itemCartCount = 0;
};
} // namespace spectree
} // namespace pappso
