/*
 * 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.topology.PathService;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiConnection;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.topo.Highlights;
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;

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

    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 Set<Link> allPathLinks;

    private enum Mode {
        SHORTEST, DISJOINT, SRLG
    }

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

    private PathService pathService;

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


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


    @Override
    public void init(UiConnection connection, ServiceDirectory directory) {
        super.init(connection, directory);
        pathService = directory.get(PathService.class);
    }

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

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

    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);
            if (src.equals(dst)) {
                dst = null;
            }
            findAndSendPaths();
        }
    }

    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);
            if (src.equals(dst)) {
                src = null;
            }
            findAndSendPaths();
        }
    }

    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;
            findAndSendPaths();
        }
    }

    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);
            currentMode = (mode.equals("shortest") ?
                    Mode.SHORTEST : (mode.equals("disjoint") ?
                    Mode.DISJOINT : Mode.SRLG));
            //TODO: add support for SRLG
            if (currentMode.equals(Mode.SHORTEST)) {
                findAndSendPaths();
            } else {
                findAndSendDisjointPaths();
            }
        }
    }

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

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

    private void findAndSendPaths() {
        if (src != null && dst != null) {
            paths = ImmutableList.copyOf(pathService.getPaths(src, dst));
            pathIndex = 0;

            ImmutableSet.Builder<Link> builder = ImmutableSet.builder();
            paths.forEach(path -> path.links().forEach(builder::add));
            allPathLinks = builder.build();
        } else {
            paths = ImmutableList.of();
            allPathLinks = ImmutableSet.of();
        }
        hilightAndSendPaths();
    }

    private void findAndSendDisjointPaths() {
        log.info("src={}; dst={}; mode={}", src, dst, currentMode);
        if (src != null && dst != null) {
            log.info("test" + src + dst);
            paths = ImmutableList.copyOf(pathService.getDisjointPaths(src, dst));
            pathIndex = 0;

            ImmutableSet.Builder<Link> builder = ImmutableSet.builder();
            paths.forEach(path -> {
                DisjointPath dp = (DisjointPath) path;
                builder.addAll(dp.primary().links());
                builder.addAll(dp.backup().links());
            });
            allPathLinks = builder.build();
        } else {
            paths = ImmutableList.of();
            allPathLinks = ImmutableSet.of();
        }
        hilightAndSendPaths();
    }

    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();
        for (PathLink plink : linkMap.biLinks()) {
            plink.computeHilight(selectedPathLinks, allPathLinks);
            highlights.add(plink.highlight(null));
        }

        sendMessage(TopoJson.highlightsMessage(highlights));
    }

    /*
    private void addDeviceBadge(Highlights h, DeviceId devId, int n) {
        DeviceHighlight dh = new DeviceHighlight(devId.toString());
        dh.setBadge(createBadge(n));
        h.add(dh);
    }

    private NodeBadge createBadge(int n) {
        Status status = n > 3 ? Status.ERROR : Status.WARN;
        String noun = n > 3 ? "(critical)" : "(problematic)";
        String msg = "Egress links: " + n + " " + noun;
        return NodeBadge.number(status, n, msg);
    }
   */

}