/*
 * 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.onosproject.pathpainter;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.onlab.osgi.ServiceDirectory;
import org.onosproject.net.DeviceId;
import org.onosproject.net.DisjointPath;
import org.onosproject.net.ElementId;
import org.onosproject.net.HostId;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.topology.GeoDistanceLinkWeight;
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.PathService;
import org.onosproject.net.topology.TopologyEvent;
import org.onosproject.net.topology.TopologyListener;
import org.onosproject.net.topology.TopologyService;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiConnection;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.topo.DeviceHighlight;
import org.onosproject.ui.topo.Highlights;
import org.onosproject.ui.topo.HostHighlight;
import org.onosproject.ui.topo.NodeBadge;
import org.onosproject.ui.topo.TopoJson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * ONOS UI PathPainter Topology-Overlay message handler.
 */
public class PathPainterTopovMessageHandler extends UiMessageHandler {

    private static final String PAINTER_CLEAR = "ppTopovClear";
    private static final String PAINTER_SET_SRC = "ppTopovSetSrc";
    private static final String PAINTER_SET_DST = "ppTopovSetDst";
    private static final String PAINTER_SWAP_SRC_DST = "ppTopovSwapSrcDst";
    private static final String PAINTER_SET_MODE = "ppTopovSetMode";

    private static final String PAINTER_NEXT_PATH = "ppTopovNextPath";
    private static final String PAINTER_PREV_PATH = "ppTopovPrevPath";

    private static final String ID = "id";
    private static final String MODE = "mode";
    private static final String TYPE = "type";
    private static final String SWITCH = "switch";
    private static final String ENDSTATION = "endstation";
    public static final String DST = "Dst";
    public static final String SRC = "Src";
    // Delay for showHighlights event processing on GUI client side to
    // account for addLink animation.
    public static final int DELAY_MS = 1100;

    private final TopologyListener topologyListener = new InternalTopologyListener();

    private Set<Link> allPathLinks;
    private boolean listenersRemoved;
    private LinkWeight linkData;
    private int highlightDelay;

    private enum Mode {
        SHORTEST, DISJOINT, GEODATA, SRLG, INVALID
    }

    private final Logger log = LoggerFactory.getLogger(getClass());

    private PathService pathService;

    private ElementId src, dst;
    private String srcType, dstType;
    private Mode currentMode = Mode.SHORTEST;
    private List<Path> paths;
    private int pathIndex;

    protected TopologyService topologyService;


    // ===============-=-=-=-=-=-======================-=-=-=-=-=-=-================================


    @Override
    public void init(UiConnection connection, ServiceDirectory directory) {
        super.init(connection, directory);
        pathService = directory.get(PathService.class);
        topologyService = directory.get(TopologyService.class);
        linkData = new GeoDistanceLinkWeight(directory.get(DeviceService.class));
        addListeners();
    }


    @Override
    public void destroy() {
        removeListeners();
        super.destroy();
    }

    @Override
    protected Collection<RequestHandler> createRequestHandlers() {
        return ImmutableSet.of(
                new ClearHandler(),
                new SetSrcHandler(),
                new SetDstHandler(),
                new SwapSrcDstHandler(),
                new NextPathHandler(),
                new PrevPathHandler(),
                new SetModeHandler()
        );
    }

    // === -------------------------
    // === Handler classes

    private final class ClearHandler extends RequestHandler {

        public ClearHandler() {
            super(PAINTER_CLEAR);
        }

        @Override
        public void process(long sid, ObjectNode payload) {
            src = null;
            dst = null;
            sendMessage(TopoJson.highlightsMessage(new Highlights()));
        }
    }

    private final class SetSrcHandler extends RequestHandler {

        public SetSrcHandler() {
            super(PAINTER_SET_SRC);
        }

        @Override
        public void process(long sid, ObjectNode payload) {
            String id = string(payload, ID);
            src = elementId(id);
            srcType = string(payload, TYPE);
            if (src.equals(dst)) {
                dst = null;
            }
            sendMessage(TopoJson.highlightsMessage(addBadge(new Highlights(),
                                                            srcType,
                                                            src.toString(),
                                                            SRC)));
            findAndSendPaths(currentMode);
        }
    }

    private final class SetDstHandler extends RequestHandler {
        public SetDstHandler() {
            super(PAINTER_SET_DST);
        }

        @Override
        public void process(long sid, ObjectNode payload) {
            String id = string(payload, ID);
            dst = elementId(id);
            dstType = string(payload, TYPE);
            if (src.equals(dst)) {
                src = null;
            }

            sendMessage(TopoJson.highlightsMessage(addBadge(new Highlights(),
                                                            dstType,
                                                            dst.toString(),
                                                            DST)));
            findAndSendPaths(currentMode);
        }
    }

    private final class SwapSrcDstHandler extends RequestHandler {
        public SwapSrcDstHandler() {
            super(PAINTER_SWAP_SRC_DST);
        }

        @Override
        public void process(long sid, ObjectNode payload) {
            ElementId temp = src;
            src = dst;
            dst = temp;
            String s = srcType;
            srcType = dstType;
            dstType = s;
            findAndSendPaths(currentMode);
        }
    }


    private final class NextPathHandler extends RequestHandler {
        public NextPathHandler() {
            super(PAINTER_NEXT_PATH);
        }

        @Override
        public void process(long sid, ObjectNode payload) {
            pathIndex = (pathIndex >= paths.size() - 1 ? 0 : pathIndex + 1);
            hilightAndSendPaths();
        }
    }

    private final class PrevPathHandler extends RequestHandler {
        public PrevPathHandler() {
            super(PAINTER_PREV_PATH);
        }

        @Override
        public void process(long sid, ObjectNode payload) {
            pathIndex = (pathIndex <= 0 ? paths.size() - 1 : pathIndex - 1);
            hilightAndSendPaths();
        }
    }

    private final class SetModeHandler extends RequestHandler {
        public SetModeHandler() {
            super(PAINTER_SET_MODE);
        }

        @Override
        public void process(long sid, ObjectNode payload) {
            String mode = string(payload, MODE);
            switch (mode) {
                case "shortest":
                    currentMode = Mode.SHORTEST;
                    break;
                case "disjoint":
                    currentMode = Mode.DISJOINT;
                    break;
                case "geodata":
                    currentMode = Mode.GEODATA;
                    break;
                case "srlg":
                    currentMode = Mode.SRLG;
                    break;
                default:
                    currentMode = Mode.INVALID;
                    break;
            }
            //TODO: add support for SRLG
            findAndSendPaths(currentMode);
        }
    }

    // === ------------

    private ElementId elementId(String id) {
        try {
            return DeviceId.deviceId(id);
        } catch (IllegalArgumentException e) {
            return HostId.hostId(id);
        }
    }

    private void findAndSendPaths(Mode mode) {
        log.debug("src={}; dst={}; mode={}", src, dst, currentMode);
        if (src != null && dst != null) {
            pathIndex = 0;
            ImmutableSet.Builder<Link> builder = ImmutableSet.builder();
            if (mode.equals(Mode.SHORTEST)) {
                paths = ImmutableList.copyOf(pathService.getPaths(src, dst));
                allPathLinks = buildPaths(builder).build();
            } else if (mode.equals(Mode.DISJOINT)) {
                paths = ImmutableList.copyOf(pathService.getDisjointPaths(src, dst));
                allPathLinks = buildDisjointPaths(builder).build();
            } else if (mode.equals(Mode.GEODATA)) {
                paths = ImmutableList.copyOf(pathService.getPaths(src, dst, linkData));
                allPathLinks = buildPaths(builder).build();
            } else {
                log.info("Unsupported MODE");
            }
        } else {
            paths = ImmutableList.of();
            allPathLinks = ImmutableSet.of();
        }
        hilightAndSendPaths();

    }

    private ImmutableSet.Builder<Link> buildPaths(ImmutableSet.Builder<Link> pathBuilder) {
        paths.forEach(path -> path.links().forEach(pathBuilder::add));
        return pathBuilder;
    }

    private ImmutableSet.Builder<Link> buildDisjointPaths(ImmutableSet.Builder<Link> pathBuilder) {
        paths.forEach(path -> {
            DisjointPath dp = (DisjointPath) path;
            pathBuilder.addAll(dp.primary().links());
            pathBuilder.addAll(dp.backup().links());
        });
        return pathBuilder;
    }

    private void hilightAndSendPaths() {
        PathLinkMap linkMap = new PathLinkMap();
        allPathLinks.forEach(linkMap::add);

        Set<Link> selectedPathLinks;

        // Prepare two working sets; one containing selected path links and
        // the other containing all paths links.
        if (currentMode.equals(Mode.DISJOINT)) {
            DisjointPath dp = (DisjointPath) paths.get(pathIndex);
            selectedPathLinks = paths.isEmpty() ?
                    ImmutableSet.of() : Sets.newHashSet(dp.primary().links());
            selectedPathLinks.addAll(dp.backup().links());
        } else {
            selectedPathLinks = paths.isEmpty() ?
                    ImmutableSet.of() : ImmutableSet.copyOf(paths.get(pathIndex).links());
        }
        Highlights highlights = new Highlights();
        if (highlightDelay > 0) {
            highlights.delay(highlightDelay);
        }
        for (PathLink plink : linkMap.biLinks()) {
            plink.computeHilight(selectedPathLinks, allPathLinks);
            highlights.add(plink.highlight(null));
        }
        if (src != null) {
            highlights = addBadge(highlights, srcType, src.toString(), SRC);
        }
        if (dst != null) {
            highlights = addBadge(highlights, dstType, dst.toString(), DST);
        }
        sendMessage(TopoJson.highlightsMessage(highlights));
    }

    private Highlights addBadge(Highlights highlights, String type, String elemId, String src) {
        if (SWITCH.equals(type)) {
            highlights = addDeviceBadge(highlights, elemId, src);
        } else if (ENDSTATION.equals(type)) {
            highlights = addHostBadge(highlights, elemId, src);
        }
        return highlights;
    }

    private Highlights addDeviceBadge(Highlights h, String elemId, String type) {
        DeviceHighlight dh = new DeviceHighlight(elemId);
        dh.setBadge(createBadge(type));
        h.add(dh);
        return h;
    }

    private Highlights addHostBadge(Highlights h, String elemId, String type) {
        HostHighlight hh = new HostHighlight(elemId);
        hh.setBadge(createBadge(type));
        h.add(hh);
        return h;
    }

    private NodeBadge createBadge(String type) {
        return NodeBadge.text(type);
    }

    private synchronized void addListeners() {
        listenersRemoved = false;
        topologyService.addListener(topologyListener);
    }

    private synchronized void removeListeners() {
        if (!listenersRemoved) {
            listenersRemoved = true;
            topologyService.removeListener(topologyListener);
        }
    }

    // Link event listener.
    private class InternalTopologyListener implements TopologyListener {
        @Override
        public void event(TopologyEvent event) {
            highlightDelay = DELAY_MS;
            findAndSendPaths(currentMode);
            highlightDelay = 0;
        }
    }

}