/*
 * 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.ui.impl.topo;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableSet;
import org.onlab.osgi.ServiceDirectory;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiConnection;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.impl.UiWebSocket;
import org.onosproject.ui.model.topo.UiClusterMember;
import org.onosproject.ui.model.topo.UiNode;
import org.onosproject.ui.model.topo.UiRegion;
import org.onosproject.ui.model.topo.UiSynthLink;
import org.onosproject.ui.model.topo.UiTopoLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/*
 NOTES:

    The original topology view message handler was broken into two classes
    TopologyViewMessageHandler, and TopologyViewMessageHandlerBase.
    We do not need to follow that model necessarily. Starting with a
    single class, and breaking it apart later if necessary.

    Need to figure out the connection between this message handler and the
    new way of doing things with UiTopoSession...

 */

/**
 * Server-side component for interacting with the new "Region aware" topology
 * view in the Web UI.
 */
public class Topo2ViewMessageHandler extends UiMessageHandler {

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

    // === Inbound event identifiers
    private static final String START = "topo2Start";
    private static final String NAV_REGION = "topo2navRegion";
    private static final String STOP = "topo2Stop";
    private static final String UPDATE_META2 = "updateMeta2";

    // === Outbound event identifiers
    private static final String ALL_INSTANCES = "topo2AllInstances";
    private static final String CURRENT_LAYOUT = "topo2CurrentLayout";
    private static final String CURRENT_REGION = "topo2CurrentRegion";
    private static final String PEER_REGIONS = "topo2PeerRegions";


    private UiTopoSession topoSession;
    private Topo2Jsonifier t2json;


    @Override
    public void init(UiConnection connection, ServiceDirectory directory) {
        super.init(connection, directory);

        // get the topo session from the UiWebSocket
        topoSession = ((UiWebSocket) connection).topoSession();
        t2json = new Topo2Jsonifier(directory, connection.userName());
    }

    @Override
    protected Collection<RequestHandler> createRequestHandlers() {
        return ImmutableSet.of(
                new Topo2Start(),
                new Topo2NavRegion(),
                new Topo2Stop(),
                new Topo2UpdateMeta()
        );
    }

    // ==================================================================


    private ObjectNode mkLayoutMessage(UiTopoLayout currentLayout) {
        List<UiTopoLayout> crumbs = topoSession.breadCrumbs();
        return t2json.layout(currentLayout, crumbs);
    }

    private ObjectNode mkRegionMessage(UiTopoLayout currentLayout) {
        UiRegion region = topoSession.getRegion(currentLayout);
        Set<UiRegion> kids = topoSession.getSubRegions(currentLayout);
        List<UiSynthLink> links = topoSession.getLinks(currentLayout);
        return t2json.region(region, kids, links);
    }

    private ObjectNode mkPeersMessage(UiTopoLayout currentLayout) {
        Set<UiNode> peers = topoSession.getPeerNodes(currentLayout);
        ObjectNode peersPayload = objectNode();
        peersPayload.set("peers", t2json.closedNodes(peers));
        return peersPayload;
    }


    private final class Topo2Start extends RequestHandler {
        private Topo2Start() {
            super(START);
        }

        @Override
        public void process(ObjectNode payload) {
            // client view is ready to receive data to display; so start up
            // server-side processing, and send over initial state

            log.debug("topo2Start: {}", payload);

            // this may be a little heavyweight, but it might be safer to do
            //  this than make assumptions about the order in which devices
            //  and regions are added... and thus internal linkages set up
            //  correctly
            topoSession.refreshModel();

            // start with the list of ONOS cluster members
            List<UiClusterMember> instances = topoSession.getAllInstances();
            sendMessage(ALL_INSTANCES, t2json.instances(instances));


            // Send layout, region, peers data...

            // this is the layout that the user has chosen to display
            UiTopoLayout currentLayout = topoSession.currentLayout();
            sendMessage(CURRENT_LAYOUT, mkLayoutMessage(currentLayout));

            // this is the region that is associated with the current layout
            //   this message includes details of the sub-regions, devices,
            //   hosts, and links within the region
            //   (as well as layer-order hints)
            sendMessage(CURRENT_REGION, mkRegionMessage(currentLayout));

            // these are the regions/devices that are siblings to this region
            sendMessage(PEER_REGIONS, mkPeersMessage(currentLayout));
        }
    }

    private final class Topo2NavRegion extends RequestHandler {
        private Topo2NavRegion() {
            super(NAV_REGION);
        }

        @Override
        public void process(ObjectNode payload) {
            String rid = string(payload, "rid");
            log.debug("topo2navRegion: rid={}", rid);

            // NOTE: we are NOT re-issuing information about the cluster nodes

            // switch to the selected region...
            topoSession.navToRegion(rid);

            // re-send layout, region, peers data...
            UiTopoLayout currentLayout = topoSession.currentLayout();
            sendMessage(CURRENT_LAYOUT, mkLayoutMessage(currentLayout));
            sendMessage(CURRENT_REGION, mkRegionMessage(currentLayout));
            sendMessage(PEER_REGIONS, mkPeersMessage(currentLayout));
        }
    }

    private final class Topo2Stop extends RequestHandler {
        private Topo2Stop() {
            super(STOP);
        }

        @Override
        public void process(ObjectNode payload) {
            // client view has gone away; so shut down server-side processing
            // TODO: implement...

            log.debug("topo2Stop: {}", payload);

            // OLD CODE DID THE FOLLOWING...
//            removeListeners();
//            stopSummaryMonitoring();
//            traffic.stopMonitoring();
        }
    }

    private final class Topo2UpdateMeta extends RequestHandler {
        private Topo2UpdateMeta() {
            super(UPDATE_META2);
        }

        @Override
        public void process(ObjectNode payload) {
            t2json.updateMeta(payload);
        }
    }

}
