/*
 * Copyright 2017 HugeGraph Authors
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to You 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 com.baidu.hugegraph.traversal.algorithm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.tinkerpop.gremlin.structure.Edge;

import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.query.QueryResults;
import com.baidu.hugegraph.structure.HugeEdge;
import com.baidu.hugegraph.type.define.Directions;
import com.baidu.hugegraph.util.CollectionUtil;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.InsertionOrderUtil;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

public class SingleSourceShortestPathTraverser extends HugeTraverser {

    public SingleSourceShortestPathTraverser(HugeGraph graph) {
        super(graph);
    }

    public WeightedPaths singleSourceShortestPaths(Id sourceV, Directions dir,
                                                   String label, String weight,
                                                   long degree, long skipDegree,
                                                   long capacity, long limit) {
        E.checkNotNull(sourceV, "source vertex id");
        this.checkVertexExist(sourceV, "source vertex");
        E.checkNotNull(dir, "direction");
        checkDegree(degree);
        checkCapacity(capacity);
        checkSkipDegree(skipDegree, degree, capacity);
        checkLimit(limit);

        Id labelId = this.getEdgeLabelId(label);
        Traverser traverser = new Traverser(sourceV, dir, labelId, weight,
                                            degree, skipDegree, capacity,
                                            limit);
        while (true) {
            // Found, reach max depth or reach capacity, stop searching
            traverser.forward();
            if (traverser.done()) {
                return traverser.shortestPaths();
            }
            checkCapacity(traverser.capacity, traverser.size, "shortest path");
        }
    }

    public NodeWithWeight weightedShortestPath(Id sourceV, Id targetV,
                                               Directions dir, String label,
                                               String weight, long degree,
                                               long skipDegree, long capacity) {
        E.checkNotNull(sourceV, "source vertex id");
        this.checkVertexExist(sourceV, "source vertex");
        E.checkNotNull(dir, "direction");
        E.checkNotNull(weight, "weight property");
        checkDegree(degree);
        checkCapacity(capacity);
        checkSkipDegree(skipDegree, degree, capacity);

        Id labelId = this.getEdgeLabelId(label);
        Traverser traverser = new Traverser(sourceV, dir, labelId, weight,
                                            degree, skipDegree, capacity,
                                            NO_LIMIT);
        while (true) {
            traverser.forward();
            Map<Id, NodeWithWeight> results = traverser.shortestPaths();
            if (results.containsKey(targetV) || traverser.done()) {
                return results.get(targetV);
            }
            checkCapacity(traverser.capacity, traverser.size, "shortest path");
        }
    }

    private class Traverser {

        private WeightedPaths findingNodes = new WeightedPaths();
        private WeightedPaths foundNodes = new WeightedPaths();
        private Set<NodeWithWeight> sources;
        private Id source;
        private final Directions direction;
        private final Id label;
        private final String weight;
        private final long degree;
        private final long skipDegree;
        private final long capacity;
        private final long limit;
        private long size;
        private boolean done = false;

        public Traverser(Id sourceV, Directions dir, Id label, String weight,
                         long degree, long skipDegree, long capacity,
                         long limit) {
            this.source = sourceV;
            this.sources = ImmutableSet.of(new NodeWithWeight(
                           0D, new Node(sourceV, null)));
            this.direction = dir;
            this.label = label;
            this.weight = weight;
            this.degree = degree;
            this.skipDegree = skipDegree;
            this.capacity = capacity;
            this.limit = limit;
            this.size = 0L;
        }

        /**
         * Search forward from source
         */
        public void forward() {
            long degree = this.skipDegree > 0L ? this.skipDegree : this.degree;
            for (NodeWithWeight node : this.sources) {
                Iterator<Edge> edges = edgesOfVertex(node.node().id(),
                                                     this.direction,
                                                     this.label, degree);
                edges = this.skipSuperNodeIfNeeded(edges);
                while (edges.hasNext()) {
                    HugeEdge edge = (HugeEdge) edges.next();
                    Id target = edge.id().otherVertexId();

                    if (this.foundNodes.containsKey(target) ||
                        this.source.equals(target)) {
                        // Already find shortest path for target, skip
                        continue;
                    }

                    double currentWeight = this.edgeWeight(edge);
                    double weight = currentWeight + node.weight();
                    NodeWithWeight nw = new NodeWithWeight(weight, target, node);
                    NodeWithWeight exist = this.findingNodes.get(target);
                    if (exist == null || weight < exist.weight()) {
                        /*
                         * There are 2 scenarios to update finding nodes:
                         * 1. The 'target' found first time, add current path
                         * 2. Already exist path for 'target' and current
                         *    path is shorter, update path for 'target'
                         */
                        this.findingNodes.put(target, nw);
                    }
                }
            }

            Map<Id, NodeWithWeight> sorted = CollectionUtil.sortByValue(
                                             this.findingNodes, true);
            double minWeight = 0;
            Set<NodeWithWeight> newSources = InsertionOrderUtil.newSet();
            for (Map.Entry<Id, NodeWithWeight> entry : sorted.entrySet()) {
                Id id = entry.getKey();
                NodeWithWeight wn = entry.getValue();
                if (minWeight == 0) {
                    minWeight = wn.weight();
                } else if (wn.weight() > minWeight) {
                    break;
                }
                // Move shortest paths from 'findingNodes' to 'foundNodes'
                this.foundNodes.put(id, wn);
                if (this.limit != NO_LIMIT &&
                    this.foundNodes.size() >= this.limit) {
                    this.done = true;
                    return;
                }
                this.findingNodes.remove(id);
                // Re-init 'sources'
                newSources.add(wn);
            }
            this.sources = newSources;
            if (this.sources.isEmpty()) {
                this.done = true;
            }
        }

        public boolean done() {
            return this.done;
        }

        public WeightedPaths shortestPaths() {
            return this.foundNodes;
        }

        private double edgeWeight(HugeEdge edge) {
            double edgeWeight;
            if (this.weight == null ||
                !edge.property(this.weight).isPresent()) {
                edgeWeight = 1.0;
            } else {
                edgeWeight = edge.value(this.weight);
            }
            return edgeWeight;
        }

        private Iterator<Edge> skipSuperNodeIfNeeded(Iterator<Edge> edges) {
            if (this.skipDegree <= 0L) {
                return edges;
            }
            List<Edge> edgeList = new ArrayList<>();
            int count = 0;
            while (edges.hasNext()) {
                if (count < this.degree) {
                    edgeList.add(edges.next());
                }
                if (count >= this.skipDegree) {
                    return QueryResults.emptyIterator();
                }
                count++;
            }
            return edgeList.iterator();
        }
    }

    public static class NodeWithWeight implements Comparable<NodeWithWeight> {

        private final double weight;
        private final Node node;

        public NodeWithWeight(double weight, Node node) {
            this.weight = weight;
            this.node = node;
        }

        public NodeWithWeight(double weight, Id id, NodeWithWeight prio) {
            this(weight, new Node(id, prio.node()));
        }

        public double weight() {
            return weight;
        }

        public Node node() {
            return this.node;
        }

        public Map<String, Object> toMap() {
            return ImmutableMap.of("weight", this.weight,
                                   "vertices", this.node().path());
        }

        @Override
        public int compareTo(NodeWithWeight other) {
            return Double.compare(this.weight, other.weight);
        }
    }

    public static class WeightedPaths extends LinkedHashMap<Id, NodeWithWeight> {

        private static final long serialVersionUID = -313873642177730993L;

        public Set<Id> vertices() {
            Set<Id> vertices = new HashSet<>();
            vertices.addAll(this.keySet());
            for (NodeWithWeight nw : this.values()) {
                vertices.addAll(nw.node().path());
            }
            return vertices;
        }

        public Map<Id, Map<String, Object>> toMap() {
            Map<Id, Map<String, Object>> results = new HashMap<>();
            for (Map.Entry<Id, NodeWithWeight> entry : this.entrySet()) {
                Id source = entry.getKey();
                NodeWithWeight nw = entry.getValue();
                Map<String, Object> result = nw.toMap();
                results.put(source, result);
            }
            return results;
        }
    }
}
