// SupportFunction.hpp
//
//     Created on: 04. 03. 2018
//         Author: Jan Uhlik
//    Modified by:
//
// Copyright (c) 2017 Czech Technical University in Prague | Faculty of Information Technology. All rights reserved.
// Git repository: https://gitlab.fit.cvut.cz/algorithms-library-toolkit/automata-library

#ifndef ALIB2_GRAPHFUNCTION_HPP
#define ALIB2_GRAPHFUNCTION_HPP

#include <limits>
#include <graph/GraphClasses.hpp>
#include <grid/GridClasses.hpp>

namespace common {

class SupportFunction {
// ---------------------------------------------------------------------------------------------------------------------
 public:

  template<typename TNode, typename TEdge>
  static
  TNode const &
  other(const TEdge &e, const TNode &n);

  template<typename TNode, typename TEdge>
  static
  TNode &
  other(TEdge &e, const TNode &n);

// ---------------------------------------------------------------------------------------------------------------------

  template<typename TGraph>
  static
  typename TGraph::edge_type::weight_type
  getMinEdgeValue(const TGraph &graph);

  template<typename TCoordinate, typename TEdge>
  static
  typename grid::WeightedSquareGrid8<TCoordinate, TEdge>::edge_type::weight_type
  getMinEdgeValue(const grid::WeightedSquareGrid8<TCoordinate, TEdge> &graph);

  template<typename TCoordinate, typename TEdge>
  static
  typename grid::WeightedSquareGrid4<TCoordinate, TEdge>::edge_type::weight_type
  getMinEdgeValue(const grid::WeightedSquareGrid4<TCoordinate, TEdge> &graph);

// ---------------------------------------------------------------------------------------------------------------------

};

// ====================================================================================================================

template<typename TNode, typename TEdge>
TNode const &
SupportFunction::other(const TEdge &e, const TNode &n) {
  if (n == e.first) return e.second;
  return e.first;
}

template<typename TNode, typename TEdge>
TNode &
SupportFunction::other(TEdge &e, const TNode &n) {
  if (n == e.first) return e.second;
  return e.first;
}

// ---------------------------------------------------------------------------------------------------------------------

template<typename TGraph>
typename TGraph::edge_type::weight_type
SupportFunction::getMinEdgeValue(const TGraph &graph) {
  using weight_type = typename TGraph::edge_type::weight_type;
  weight_type eps = std::numeric_limits<weight_type>::max();

  for (const auto &edge: graph.getEdges()) {
    if (edge.weight() < eps) {
      eps = edge.weight();
    }
  }

  return eps;
}

template<typename TCoordinate, typename TEdge>
typename grid::WeightedSquareGrid8<TCoordinate, TEdge>::edge_type::weight_type
SupportFunction::getMinEdgeValue(const grid::WeightedSquareGrid8<TCoordinate, TEdge> &graph) {
  return graph.getUnit();
}

template<typename TCoordinate, typename TEdge>
typename grid::WeightedSquareGrid4<TCoordinate, TEdge>::edge_type::weight_type
SupportFunction::getMinEdgeValue(const grid::WeightedSquareGrid4<TCoordinate, TEdge> &graph) {
  return graph.getUnit();
}

// ---------------------------------------------------------------------------------------------------------------------

} // namespace common

#endif //ALIB2_GRAPHFUNCTION_HPP
