/*
 * 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.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

import static org.onosproject.ui.topo.TopoJson.highlightsMessage;

/**
 * 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";
    private static final String DST = "Dst";
    private static final String SRC = "Src";
    // Delay for showHighlights event processing on GUI client side to
    // account for addLink animation.
    private 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(ObjectNode payload) {
            src = null;
            dst = null;
            sendMessage(highlightsMessage(new Highlights()));
        }
    }

    private final class SetSrcHandler extends RequestHandler {

        public SetSrcHandler() {
            super(PAINTER_SET_SRC);
        }

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

            sendMessage(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(ObjectNode payload) {
            String id = string(payload, ID);
            dst = elementId(id);
            dstType = string(payload, TYPE);
            if (src.equals(dst)) {
                src = null;
            }

            sendMessage(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(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(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(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(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.warn("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(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;
        }
    }

}