/*
 * Copyright 2014,2015 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.info("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;
        }
    }

}