#pragma once

#include <memory>
#include <utility>
#include "vector"
#include "algorithm"
#include "tuple"

static size_t distance;

template<typename Vertex>
class BfsVisitor {
 public:
  BfsVisitor() {
     distance_ = std::make_shared<std::pair<
        std::vector<std::tuple<Vertex, size_t, Vertex>>,
        std::pair<int, Vertex>>>();
  }

  void ExamineVertex(const Vertex &vertex) {
    for (std::tuple<Vertex, size_t, Vertex> vert : (*distance_).first) {
      if (std::get<0>(vert) == vertex) {
        distance = std::get<1>(vert) + 1;
        (*distance_).second = std::make_pair(distance, vertex);
      }
    }
  }

  void DiscoverVertex(const Vertex &vertex) {
    if ((*distance_).first.size() == 0) {
      distance = 0;
    }
    (*distance_).first.push_back(std::make_tuple(
       vertex, distance, (*distance_).second.second));
  }

  size_t DistanceTo(const Vertex &target) const {
     for (std::tuple<Vertex, size_t, Vertex> vert : (*distance_).first) {
       if (std::get<0>(vert) == target) {
         return std::get<1>(vert);
       }
     }
     return 9999;
  }
  Vertex Parent(const Vertex &vertex) const {
    for (std::tuple<Vertex, size_t, Vertex> vert : (*distance_).first) {
      if (std::get<0>(vert) == vertex) {
        return std::get<2>(vert);
      }
    }
    return 9999;
  }

 private:
  std::shared_ptr<std::pair
    <std::vector<std::tuple<Vertex, size_t, Vertex>>,
  std::pair<int, Vertex>>
  > distance_;
};