// ****************************************************************************
//
//          Aevol - An in silico experimental evolution platform
//
// ****************************************************************************
//
// Copyright: See the AUTHORS file provided with the package or <www.aevol.fr>
// Web: http://www.aevol.fr/
// E-mail: See <http://www.aevol.fr/contact/>
// Original Authors : Guillaume Beslon, Carole Knibbe, David Parsons
//
// 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 2 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/>.
//
// ****************************************************************************

#ifndef AEVOL_PROMOTER_H
#define AEVOL_PROMOTER_H

#include <cstdint>
#include <map>

#include "Dna.h"
#include "Strand.h"

namespace aevol {
  class Rna;


#ifdef BASE_2
constexpr const char* PROM_SEQ_LEAD = "0101011001110010010110";
constexpr const char* PROM_SEQ_LAG  = "1010100110001101101001";
#endif

class Promoter {
 public:
  Promoter() = delete;
  Promoter(const Promoter& other) = default;
  Promoter(Promoter&& clone) = default;
  Promoter& operator=(const Promoter& clone) = default;
  Promoter& operator=(Promoter&& clone) = default;
  virtual ~Promoter() = default;

  Promoter(int32_t t_pos, int8_t nb_errors, Strand strand);

  static int8_t is_promoter_leading(const Dna& dna, Dna::size_type pos);
  static int8_t is_promoter_lagging(const Dna& dna, Dna::size_type pos);

  auto pos() const { return pos_; }
  auto nb_errors() const { return nb_errors_; }
  auto basal_level() const { return basal_level_; }
  auto strand() const { return strand_; }
  const auto* rna() const { return rna_; }
  auto* rna() { return const_cast<Rna*>(static_cast<const Promoter&>(*this).rna()); }

  void set_pos(Dna::size_type pos) { pos_ = pos; }
  void set_strand(Strand strand) { strand_ = strand; }
  void reset_rna(Rna* rna = nullptr) { rna_ = rna; }

 protected:
  Dna::size_type pos_ = -1;
  int8_t nb_errors_ = -1;
  double basal_level_ = 0.;
  Strand strand_;

  Rna* rna_ = nullptr;
};

}

#endif //AEVOL_PROMOTER_H
