/*
 * Copyright 2016-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.sfcweb;

import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;

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

import jersey.repackaged.com.google.common.collect.Lists;

import org.onlab.osgi.DefaultServiceDirectory;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Element;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.Link;
import org.onosproject.net.host.HostService;
import org.onosproject.net.link.LinkService;
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.onosproject.vtnrsc.FiveTuple;
import org.onosproject.vtnrsc.LoadBalanceId;
import org.onosproject.vtnrsc.PortChain;
import org.onosproject.vtnrsc.PortChainId;
import org.onosproject.vtnrsc.PortPair;
import org.onosproject.vtnrsc.PortPairId;
import org.onosproject.vtnrsc.VirtualPort;
import org.onosproject.vtnrsc.VirtualPortId;
import org.onosproject.vtnrsc.portchain.PortChainService;
import org.onosproject.vtnrsc.portpair.PortPairService;
import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
import org.onosproject.vtnrsc.service.VtnRscService;
import org.onosproject.vtnrsc.virtualport.VirtualPortService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableSet;

/**
 * SFC web gui topology-overlay message handler.
 */
public class SfcwebUiTopovMessageHandler extends UiMessageHandler {

    private static final String SAMPLE_TOPOV_DISPLAY_START = "sfcwebTopovDisplayStart";
    private static final String SAMPLE_TOPOV_DISPLAY_SFC = "showSfcInfo";
    private static final String SAMPLE_TOPOV_DISPLAY_STOP = "sfcTopovClear";
    private static final String CONFIG_SFP_MSG = "configSfpMessage";
    private static final String SAMPLE_TOPOV_SHOW_SFC_PATH = "showSfcPath";
    private static final String ID = "id";
    private static final String MODE = "mode";
    private static final String CLASSIFIER = "CLS";
    private static final String FORWARDER = "SFF";

    private static final Link[] EMPTY_LINK_SET = new Link[0];

    private enum Mode {
        IDLE, MOUSE, LINK
    }

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

    private HostService hostService;
    private LinkService linkService;
    private TimerTask demoTask = null;
    private Mode currentMode = Mode.IDLE;
    private Element elementOfNote;
    private Link[] linkSet = EMPTY_LINK_SET;

    protected PortPairService portPairService;
    protected VtnRscService vtnRscService;
    protected VirtualPortService virtualPortService;
    protected PortChainService portChainService;
    protected PortPairGroupService portPairGroupService;

    @Override
    public void init(UiConnection connection, ServiceDirectory directory) {
        super.init(connection, directory);
        hostService = directory.get(HostService.class);
        linkService = directory.get(LinkService.class);
        portChainService = directory.get(PortChainService.class);
        portPairService = directory.get(PortPairService.class);
        portPairGroupService = directory.get(PortPairGroupService.class);
    }

    @Override
    protected Collection<RequestHandler> createRequestHandlers() {
        return ImmutableSet.of(
                new DisplayStartHandler(),
                new DisplayStopHandler(),
                new ConfigSfpMsg()
        );
    }

    /**
     * Handler classes.
     */
    private final class DisplayStartHandler extends RequestHandler {
        public DisplayStartHandler() {
            super(SAMPLE_TOPOV_DISPLAY_START);
        }
        @Override
        public void process(long sid, ObjectNode payload) {
            String mode = string(payload, MODE);
            PortChainService pcs = get(PortChainService.class);
            Iterable<PortChain> portChains = pcs.getPortChains();
            ObjectNode result = objectNode();

            ArrayNode arrayNode = arrayNode();

            for (final PortChain portChain : portChains) {
                arrayNode.add(portChain.portChainId().value().toString());
            }
            result.putArray("a").addAll(arrayNode);

            sendMessage(SAMPLE_TOPOV_DISPLAY_SFC, sid, result);
        }
    }

    private final class DisplayStopHandler extends RequestHandler {
        public DisplayStopHandler() {
            super(SAMPLE_TOPOV_DISPLAY_STOP);
        }

        @Override
        public void process(long sid, ObjectNode payload) {
            log.debug("Stop Display");
            clearState();
            clearForMode();
            cancelTask();
        }
    }

    private final class ConfigSfpMsg extends RequestHandler {
        public ConfigSfpMsg() {
            super(CONFIG_SFP_MSG);
        }

        @Override
        public void process(long sid, ObjectNode payload) {
            String id = string(payload, ID);
            ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
            vtnRscService = serviceDirectory.get(VtnRscService.class);
            virtualPortService = serviceDirectory.get(VirtualPortService.class);

            List<String> sfcPathList = Lists.newArrayList();

            Highlights highlights = new Highlights();
            SfcLinkMap linkMap = new SfcLinkMap();

            PortChainId portChainId = PortChainId.of(id);
            boolean portChainIdExist = portChainService.exists(portChainId);
            if (!portChainIdExist) {
                log.info("portchain id doesn't exist");
                return;
            }

            PortChain portChain = portChainService.getPortChain(portChainId);

            Set<FiveTuple> fiveTupleSet = portChain.getLoadBalanceIdMapKeys();
            for (FiveTuple fiveTuple : fiveTupleSet) {
                List<PortPairId> path = portChain.getLoadBalancePath(fiveTuple);
                LoadBalanceId lbId = portChain.getLoadBalanceId(fiveTuple);
                ListIterator<PortPairId> pathIterator = path.listIterator();

                // Add source
                Host srcHost = hostService.getHost(HostId.hostId(fiveTuple.macSrc()));

                HostHighlight hSrc = new HostHighlight(srcHost.id().toString());
                hSrc.setBadge(NodeBadge.text("SRC"));
                String sfcPath = "SRC -> ";
                highlights.add(hSrc);

                DeviceId previousDeviceId = null;
                while (pathIterator.hasNext()) {

                    PortPairId portPairId = pathIterator.next();
                    PortPair portPair = portPairService.getPortPair(portPairId);
                    DeviceId deviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.egress()));
                    VirtualPort vPort = virtualPortService.getPort(VirtualPortId.portId(portPair.egress()));
                    MacAddress dstMacAddress = vPort.macAddress();
                    Host host = hostService.getHost(HostId.hostId(dstMacAddress));

                    addEdgeLinks(linkMap, host);
                    log.info("before check");
                    if (previousDeviceId != null) {
                        log.info("pdid not null");
                        if (!deviceId.equals(previousDeviceId)) {
                            // Highlight the link between devices.

                            Link link = getLinkBetweenDevices(deviceId, previousDeviceId);
                            if (link != null) {
                                linkMap.add(link);
                            }
                        }
                    }

                    DeviceHighlight dh = new DeviceHighlight(deviceId.toString());
                    if (portChain.getSfcClassifiers(lbId).contains(deviceId)) {
                        dh.setBadge(NodeBadge.text(CLASSIFIER));
                    } else {
                        dh.setBadge(NodeBadge.text(FORWARDER));
                    }

                    highlights.add(dh);

                    HostHighlight hhDst = new HostHighlight(host.id().toString());
                    hhDst.setBadge(NodeBadge.text(portPair.name()));
                    sfcPath = sfcPath + portPair.name() + "(" + vPort.fixedIps().iterator().next().ip() + ") -> ";

                    if (!portPair.ingress().equals(portPair.egress())) {
                        MacAddress srcMacAddress = virtualPortService.getPort(VirtualPortId
                                .portId(portPair.ingress()))
                                .macAddress();
                        Host hostSrc = hostService.getHost(HostId.hostId(srcMacAddress));
                        HostHighlight hhSrc = new HostHighlight(hostSrc.id().toString());
                        hhSrc.setBadge(NodeBadge.text(portPair.name()));
                        highlights.add(hhSrc);
                    }
                    highlights.add(hhDst);
                    previousDeviceId = deviceId;
                }

                // Add destination
                Host dstHost = hostService.getHost(HostId.hostId(fiveTuple.macDst()));

                HostHighlight hDst = new HostHighlight(dstHost.id().toString());
                hDst.setBadge(NodeBadge.text("DST"));
                sfcPath = sfcPath + "DST";
                highlights.add(hDst);
                sfcPathList.add(sfcPath);
            }

            for (SfcLink sfcLink : linkMap.biLinks()) {
                highlights.add(sfcLink.highlight(null));
            }
            sendHighlights(highlights);

            ObjectNode result = objectNode();
            ArrayNode arrayNode = arrayNode();
            for (String path : sfcPathList) {
                arrayNode.add(path);
            }
            result.putArray("sfcPathList").addAll(arrayNode);

            sendMessage(SAMPLE_TOPOV_SHOW_SFC_PATH, sid, result);
        }
    }

    private Link getLinkBetweenDevices(DeviceId deviceId, DeviceId previousDeviceId) {
        Set<Link> deviceLinks = linkService.getDeviceEgressLinks(deviceId);
        Set<Link> previousDeviceLinks = linkService.getDeviceIngressLinks(previousDeviceId);
        for (Link link : deviceLinks) {
            previousDeviceLinks.contains(link);
            return link;
        }
        return null;
    }

    private void addEdgeLinks(SfcLinkMap linkMap, Host host1) {
        linkMap.add(createEdgeLink(host1, true));
        linkMap.add(createEdgeLink(host1, false));
    }

    private synchronized void cancelTask() {
        if (demoTask != null) {
            demoTask.cancel();
            demoTask = null;
        }
    }

    private void clearState() {
        currentMode = Mode.IDLE;
        elementOfNote = null;
        linkSet = EMPTY_LINK_SET;
    }

    private void clearForMode() {
        sendHighlights(new Highlights());
    }

    private void sendHighlights(Highlights highlights) {
        sendMessage(TopoJson.highlightsMessage(highlights));
    }

}
