// Normalize.hpp
//
//     Created on: 01. 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

#pragma once

#include <utility>

#include "DefaultTypes.hpp"

namespace graph {

class GraphNormalize {
// ---------------------------------------------------------------------------------------------------------------------

 public:

  template<typename TNode>
  static DefaultNodeType normalizeNode(TNode &&node);

  template<typename TEdge>
  static DefaultEdgeType normalizeEdge(TEdge &&edge);

  template<typename TEdge>
  static DefaultWeightedEdgeType normalizeWeightedEdge(TEdge &&edge);

  template<typename TEdge>
  static DefaultCapacityEdgeType normalizeCapacityEdge(TEdge &&edge);

  template<typename TWeight>
  static DefaultWeightType normalizeWeight(TWeight &&weight);

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

  template<typename TCoordinate>
  static ext::pair<DefaultCoordinateType, DefaultCoordinateType> normalizeObstacle(ext::pair<TCoordinate,
                                                                                             TCoordinate> &&obstacle);

};

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

template<typename TNode>
DefaultNodeType GraphNormalize::normalizeNode(TNode &&node) {
  return DefaultNodeType(std::forward<TNode>(node));
}

template<typename TEdge>
DefaultEdgeType GraphNormalize::normalizeEdge(TEdge &&edge) {
  DefaultNodeType first = normalizeNode(edge.first);
  DefaultNodeType second = normalizeNode(edge.second);
  return DefaultEdgeType(std::move(first), std::move(second));
}

template<typename TEdge>
DefaultWeightedEdgeType GraphNormalize::normalizeWeightedEdge(TEdge &&edge) {
  DefaultNodeType first = normalizeNode(edge.first);
  DefaultNodeType second = normalizeNode(edge.second);
  DefaultWeightType weight = normalizeWeight(edge.weight());
  return DefaultWeightedEdgeType(std::move(first), std::move(second), weight);
}

template<typename TEdge>
DefaultCapacityEdgeType GraphNormalize::normalizeCapacityEdge(TEdge &&edge) {
  DefaultNodeType first = normalizeNode(edge.first);
  DefaultNodeType second = normalizeNode(edge.second);
  DefaultWeightType weight = normalizeWeight(edge.capacity());
  return DefaultCapacityEdgeType(std::move(first), std::move(second), weight);
}

template<typename TWeight>
DefaultWeightType GraphNormalize::normalizeWeight(TWeight &&weight) {
  return DefaultWeightType(std::forward<TWeight>(weight));
}

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

template<typename TCoordinate>
ext::pair<DefaultCoordinateType, DefaultCoordinateType> GraphNormalize::normalizeObstacle(ext::pair<TCoordinate,
                                                                                               TCoordinate> &&obstacle) {
  DefaultCoordinateType first = DefaultCoordinateType(obstacle.first);
  DefaultCoordinateType second = DefaultCoordinateType(obstacle.second);
  return ext::make_pair(first, second);
}

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

} // namespace graph

