#include <iostream>
#include <gudhi/Matrix.h>
#include <gudhi/persistence_matrix_options.h>

using Gudhi::persistence_matrix::Column_types;
using Gudhi::persistence_matrix::Default_options;

struct RU_rep_cycles_options : Default_options<Column_types::INTRUSIVE_LIST, true> {
  static const bool can_retrieve_representative_cycles = true;
  static const bool has_column_pairings = true;    // for barcode
  static const bool has_vine_update = true;        // for insert, remove, swap
  static const bool has_removable_columns = true;  // for remove
};

using RU_matrix = Gudhi::persistence_matrix::Matrix<RU_rep_cycles_options>;

void print_current_representative_cycles(const RU_matrix& M) {
  const auto& rc = M.get_all_representative_cycles();
  for (const auto& cycle : rc) {
    std::cout << M.get_column_dimension(cycle[0]);
    std::cout << "-cycle: ";
    for (auto index : cycle) {
      std::cout << index << ", ";
    }
    std::cout << "\n";
  }
}

void print_current_barcode(const RU_matrix& M) {
  const auto& bc = M.get_current_barcode();
  for (const auto& bar : bc) {
    std::cout << "dim" << bar.dim << ": (" << bar.birth << ", ";
    if (bar.death == -1) {std::cout << "inf"; }
    else { std::cout << bar.death; }
    std::cout << ")\n";
  }
}

template <class Matrix>
void example_3_1() {
  Matrix mp({
    {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
    {0, 8}, {5, 8}, {0, 9}, {8, 9}, {6, 8}, {2, 8}, {4, 8}, {7, 8}, {0, 7}, {1, 8}, {3, 8}
  });
  
  std::cout << "--------------------------------\n-- Step 0: input\n--------------------------------\n";
  mp.update_all_representative_cycles();
  std::cout << "* Barcode:\n";
  print_current_barcode(mp);
  std::cout << "* Representative cycles:\n";
  print_current_representative_cycles(mp);

  std::cout << "--------------------------------\n-- Step 1: remove 12\n--------------------------------\n";
  mp.remove_maximal_cell(12);
  mp.update_all_representative_cycles();
  std::cout << "* Barcode:\n";
  print_current_barcode(mp);
  std::cout << "* Representative cycles:\n";
  print_current_representative_cycles(mp);

  std::cout << "--------------------------------\n-- Step 2: remove 10\n--------------------------------\n";
  mp.remove_maximal_cell(10);
  mp.update_all_representative_cycles();
  std::cout << "* Barcode:\n";
  print_current_barcode(mp);
  std::cout << "* Representative cycles:\n";
  print_current_representative_cycles(mp);
}

int main() { example_3_1<RU_matrix>(); }
