/*
 * Copyright 2015-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.onlab.graph;

import com.google.common.collect.Sets;

import java.util.ArrayList;
import java.util.Set;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.HashSet;
import java.util.stream.Collectors;

/**
 * Suurballe shortest-path graph search algorithm capable of finding both
 * a shortest path, as well as a backup shortest path, between a source and a destination
 * such that the sum of the path lengths is minimized.
 */
public class SuurballeGraphSearch<V extends Vertex, E extends Edge<V>> extends DijkstraGraphSearch<V, E> {

    @Override
    public Result<V, E> search(Graph<V, E> graph, V src, V dst,
                               EdgeWeight<V, E> weight, int maxPaths) {
        // FIXME: This method needs to be refactored as it is difficult to follow and debug.

        // FIXME: There is a defect here triggered by 3+ edges between the same vertices,
        // which makes an attempt to produce looping paths. Protection against
        // this was added to AbstractGraphPathSearch, but the root issue remains here.

        // FIXME: There is a defect here where not all paths are truly disjoint.
        // This class needs to filter its own results to make sure that the
        // paths are indeed disjoint. Temporary fix for this is provided, but
        // the issue needs to be addressed through refactoring.
        if (weight == null) {
            weight = edge -> 1;
        }

        final EdgeWeight weightf = weight;
        DefaultResult firstDijkstraS = (DefaultResult) super.search(graph, src, dst, weight, ALL_PATHS);
        DefaultResult firstDijkstra = (DefaultResult) super.search(graph, src, null, weight, ALL_PATHS);

        //choose an arbitrary shortest path to run Suurballe on
        Path<V, E> shortPath = null;
        if (firstDijkstraS.paths().size() == 0) {
            return firstDijkstraS;
        }

        DisjointPathResult result = new DisjointPathResult(firstDijkstra, src, dst, maxPaths);

        for (Path p: firstDijkstraS.paths()) {
            shortPath = p;
            //transforms the graph so tree edges have 0 weight
            EdgeWeight<V, E> modified = edge ->
                edge instanceof ReverseEdge ? 0 :
                    weightf.weight(edge) + firstDijkstra.cost(edge.src()) - firstDijkstra.cost(edge.dst());
            EdgeWeight<V, E> modified2 = edge ->
                    weightf.weight(edge) + firstDijkstra.cost(edge.src()) - firstDijkstra.cost(edge.dst());

            //create a residual graph g' by removing all src vertices and reversing 0 length path edges
            MutableGraph<V, E> gt = mutableCopy(graph);

            Map<E, E> revToEdge = new HashMap<>();
            graph.getEdgesTo(src).forEach(gt::removeEdge);
            for (E edge: shortPath.edges()) {
                gt.removeEdge(edge);
                Edge<V> reverse = new ReverseEdge<V>(edge);
                revToEdge.put((E) reverse, edge);
                gt.addEdge((E) reverse);
            }

            //rerun dijkstra on the temporary graph to get a second path
            Result<V, E> secondDijkstra = new DijkstraGraphSearch<V, E>()
                    .search(gt, src, dst, modified, ALL_PATHS);

            Path<V, E> residualShortPath = null;
            if (secondDijkstra.paths().size() == 0) {
                result.dpps.add(new DisjointPathPair<>(shortPath, null));
                continue;
            }

            for (Path p2: secondDijkstra.paths()) {
                residualShortPath = p2;

                MutableGraph<V, E> roundTrip = mutableCopy(graph);

                List<E> tmp = roundTrip.getEdges().stream().collect(Collectors.toList());

                tmp.forEach(roundTrip::removeEdge);

                shortPath.edges().forEach(roundTrip::addEdge);

                if (residualShortPath != null) {
                    for (Edge<V> edge: residualShortPath.edges()) {
                        if (edge instanceof ReverseEdge) {
                            roundTrip.removeEdge(revToEdge.get(edge));
                        } else {
                            roundTrip.addEdge((E) edge);
                        }
                    }
                }
                //Actually build the final result
                DefaultResult lastSearch = (DefaultResult) super.search(roundTrip, src, dst, weight, ALL_PATHS);
                Path<V, E> primary = lastSearch.paths().iterator().next();
                primary.edges().forEach(roundTrip::removeEdge);

                Set<Path<V, E>> backups = super.search(roundTrip, src, dst, weight, ALL_PATHS).paths();

                // Find first backup path that does not share any nodes with the primary
                for (Path<V, E> backup : backups) {
                    if (isDisjoint(primary, backup)) {
                        result.dpps.add(new DisjointPathPair<>(primary, backup));
                        break;
                    }
                }
            }
        }

        for (int i = result.dpps.size() - 1; i > 0; i--) {
            if (result.dpps.get(i).size() <= 1) {
                result.dpps.remove(i);
            }
        }

        result.buildPaths();
        return result;
    }

    private boolean isDisjoint(Path<V, E> a, Path<V, E> b) {
        return Sets.intersection(vertices(a), vertices(b)).isEmpty();
    }

    private Set<V> vertices(Path<V, E> p) {
        Set<V> set = new HashSet<>();
        p.edges().forEach(e -> set.add(e.src()));
        set.remove(p.src());
        return set;
    }

    /**
     * Creates a mutable copy of an immutable graph.
     *
     * @param graph   immutable graph
     * @return mutable copy
     */
    private MutableGraph<V, E> mutableCopy(Graph<V, E> graph) {
        return new MutableAdjacencyListsGraph<>(graph.getVertexes(), graph.getEdges());
    }

    private static final class ReverseEdge<V extends Vertex> extends AbstractEdge<V> {
        private ReverseEdge(Edge<V> edge) {
            super(edge.dst(), edge.src());
        }

        @Override
        public String toString() {
            return "ReversedEdge " + "src=" + src() + " dst=" + dst();
        }
    }

    // Auxiliary result for disjoint path search
    private final class DisjointPathResult implements AbstractGraphPathSearch.Result<V, E> {

        private final Result<V, E> searchResult;
        private final V src, dst;
        private final int maxPaths;
        private final List<DisjointPathPair<V, E>> dpps = new ArrayList<>();
        private final Set<Path<V, E>> disjointPaths = new HashSet<>();

        private DisjointPathResult(Result<V, E> searchResult, V src, V dst, int maxPaths) {
            this.searchResult = searchResult;
            this.src = src;
            this.dst = dst;
            this.maxPaths = maxPaths;
        }

        @Override
        public V src() {
            return src;
        }

        @Override
        public V dst() {
            return dst;
        }

        @Override
        public Set<Path<V, E>> paths() {
            return disjointPaths;
        }

        private void buildPaths() {
            int paths = 0;
            for (DisjointPathPair<V, E> path: dpps) {
                disjointPaths.add(path);
                paths++;
                if (paths == maxPaths) {
                    break;
                }
            }
        }

        @Override
        public Map<V, Set<E>> parents() {
            return searchResult.parents();
        }

        @Override
        public Map<V, Double> costs() {
            return searchResult.costs();
        }
    }
}

