/* Copyright (c) 2018 -- 2022
   Charles Jordan (Hokkaido University, Sapporo, Japan),
   Michael Joswig, Lars Kastner (Technische Universitaet Berlin, Germany)

   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 3, or (at your option) any
   later version: http://www.gnu.org/licenses/gpl.txt.

   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.
-----------------------------------------------------------------------------
*/

#ifndef RANDOM_BFS_HH
#define RANDOM_BFS_HH

#include <cstdlib>
#include <unordered_set>

template<typename Node>
void randomized_bfs(const Node& initial) {
   std::unordered_set<Node> queue, seen;
   queue.insert(initial);
   Int i = 0;
   Int mod = 1;
   while(queue.size() > 0){
      if(i % mod == 0){
         if(i %(100*mod) == 0){
            mod *= 10;
         }
         std::cout << "Step: " << i << ", Queue size: " << queue.size() << std::endl;
      }
      auto it = queue.begin();
      Int pos = rand()%(queue.size());
      for(Int k=0; k<pos; k++) it++;
      const Node current(*it);
      queue.erase(it);
      seen.insert(current);
      for(const auto& neighbor: current.get_all_neighbors()){
         auto search = seen.find(neighbor);
         if (search == seen.end()) {
            auto searchInner = queue.find(neighbor);
            if(searchInner == queue.end()){
               queue.insert(neighbor);
            }
         }
      }
      i++;
   }
   std::cout << "Total triangulations: " << seen.size() << std::endl;
}

template<typename Node>
void random_walk(const Node& initial) {
   Node current(initial);
   size_type bound = CommandlineOptions::rw_size();
   size_type k = 0;
   while( k != bound || bound == -1){
      Int n = current.get_all_neighbors().size();
      std::cout << current.get_triang() << std::endl;
      Int select = rand()%n;
      Int i = 0;
      for(const auto& neighbor: current.get_all_neighbors()){
         if(i==select){
            current = neighbor;
            break;
         }
         i++;
      }
      k++;
   }
}


#endif
