/*
 *  Copyright 2016-present Open Networking Foundation
 *
 *  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 org.onosproject.net.DeviceId;
import org.onosproject.net.region.RegionId;
import org.onosproject.ui.UiTopoLayoutService;
import org.onosproject.ui.impl.UiWebSocket;
import org.onosproject.ui.model.topo.UiLinkId;
import org.onosproject.ui.model.topo.UiModelEvent;
import org.onosproject.ui.impl.topo.model.UiModelListener;
import org.onosproject.ui.impl.topo.model.UiSharedTopologyModel;
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.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Coordinates with the {@link UiTopoLayoutService} to access
 * {@link UiTopoLayout}s, and with the {@link UiSharedTopologyModel} which
 * maintains a local model of the network entities, tailored specifically
 * for displaying on the UI.
 * <p>
 * Note that an instance of this class will be created for each
 * {@link UiWebSocket} connection, and will contain
 * the state of how the topology is laid out for the logged-in user.
 * <p>
 * The expected pattern is for the {@link Topo2ViewMessageHandler} to obtain
 * a reference to the session instance (via the {@link UiWebSocket}), and
 * interact with it when topo-related events come in from the client.
 */
public class UiTopoSession implements UiModelListener {

    private static final String TOPO2_UI_MODEL_EVENT = "topo2UiModelEvent";

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

    private final UiWebSocket webSocket;
    private final String username;
    private final Topo2Jsonifier t2json;

    final UiSharedTopologyModel sharedModel;

    private boolean registered = false;

    private UiTopoLayoutService layoutService;
    private UiTopoLayout currentLayout;
    private boolean messagesEnabled = true;

    /**
     * Creates a new topology session for the specified web socket connection,
     * and references to JSONifier, shared model, and layout service.
     *
     * @param webSocket     web socket
     * @param jsonifier     JSONifier instance
     * @param model         share topology model
     * @param layoutService topology layout service
     */
    public UiTopoSession(UiWebSocket webSocket,
                         Topo2Jsonifier jsonifier,
                         UiSharedTopologyModel model,
                         UiTopoLayoutService layoutService) {
        this.webSocket = webSocket;
        this.username = webSocket.userName();
        this.t2json = jsonifier;
        this.sharedModel = model;
        this.layoutService = layoutService;
    }

    // constructs a neutered instance, for unit testing
    UiTopoSession() {
        webSocket = null;
        username = null;
        t2json = null;
        sharedModel = null;
    }

    /**
     * Initializes the session; registering with the shared model.
     */
    public void init() {
        if (!registered) {
            log.debug("{} : Registering with shared model", this);
            sharedModel.register(this);
            currentLayout = layoutService.getRootLayout();
            registered = true;
        } else {
            log.warn("already registered");
        }
    }

    /**
     * Destroys the session; unregistering from the shared model.
     */
    public void destroy() {
        if (registered) {
            log.debug("{} : Unregistering from shared model", this);
            sharedModel.unregister(this);
            registered = false;
        } else {
            log.warn("already unregistered");
        }
    }

    @Override
    public String toString() {
        return String.format("{UiTopoSession for user <%s>}", username);
    }

    @Override
    public boolean isRelevant(UiModelEvent event) {
        if (!messagesEnabled) {
            return false;
        }
        UiRegion uiRegion = sharedModel.getRegion(currentLayout.regionId());
        return uiRegion.isRelevant(event);
    }

    @Override
    public void event(UiModelEvent event) {
        // To ensure link can be created devices have to be added to the list as
        // they are created
        if (event.type() == UiModelEvent.Type.DEVICE_ADDED_OR_UPDATED &&
                event.memo() == "added") {
            UiRegion uiRegion = sharedModel.getRegion(currentLayout.regionId());
            uiRegion.newDeviceAdded(DeviceId.deviceId(event.subject().idAsString()));
        } else if (event.type() == UiModelEvent.Type.DEVICE_REMOVED) {
            UiRegion uiRegion = sharedModel.getRegion(currentLayout.regionId());
            uiRegion.deviceRemoved(DeviceId.deviceId(event.subject().idAsString()));
        }

        webSocket.sendMessage(TOPO2_UI_MODEL_EVENT, t2json.jsonEvent(event));
    }

    /**
     * Returns the current layout context.
     *
     * @return current topology layout
     */
    public UiTopoLayout currentLayout() {
        return currentLayout;
    }

    /**
     * Returns the breadcrumb trail from current layout to root. That is,
     * element 0 of the list will be the current layout; the last element
     * of the list will be the root layout. This list is guaranteed to have
     * size of at least 1.
     *
     * @return breadcrumb trail
     */
    public List<UiTopoLayout> breadCrumbs() {
        UiTopoLayout current = currentLayout;
        List<UiTopoLayout> crumbs = new ArrayList<>();
        crumbs.add(current);
        while (!current.isRoot()) {
            current = layoutService.getLayout(current.parent());
            crumbs.add(current);
        }
        return crumbs;
    }

    /**
     * Changes the current layout context to the specified layout.
     *
     * @param topoLayout new topology layout context
     */
    public void setCurrentLayout(UiTopoLayout topoLayout) {
        currentLayout = topoLayout;
    }

    /**
     * Enables or disables the transmission of topology event update messages.
     *
     * @param enabled true if messages should be sent
     */
    public void enableEvent(boolean enabled) {
        messagesEnabled = enabled;
    }

    /**
     * Returns the list of ONOS instances (cluster members).
     *
     * @return the list of ONOS instances
     */
    public List<UiClusterMember> getAllInstances() {
        return sharedModel.getClusterMembers();
    }

    /**
     * Returns the region for the specified layout.
     *
     * @param layout layout filter
     * @return region that the layout is based upon
     */
    public UiRegion getRegion(UiTopoLayout layout) {
        RegionId rid = layout.regionId();
        return rid == null ? sharedModel.getNullRegion() : sharedModel.getRegion(rid);
    }

    /**
     * Returns the regions/devices that are "peers" to this region. That is,
     * based on the layout the user is viewing, all the regions/devices that
     * are associated with layouts that share the same parent layout as this
     * layout, AND that are linked to an element within this region.
     *
     * @param layout the layout being viewed
     * @return all regions/devices that are "siblings" to this layout's region
     */
    public Set<UiNode> getPeerNodes(UiTopoLayout layout) {
        Set<UiNode> peers = new HashSet<>();

        // first, get the peer regions
        Set<UiTopoLayout> peerLayouts = layoutService.getPeerLayouts(layout.id());
        peerLayouts.forEach(l -> {
            RegionId peerRegion = l.regionId();
            peers.add(sharedModel.getRegion(peerRegion));
        });

        // now add the devices that reside in the parent region
        if (!layout.isRoot()) {
            UiTopoLayout parentLayout = layoutService.getLayout(layout.parent());
            peers.addAll(getRegion(parentLayout).devices());
        }

        // TODO: Finally, filter out regions / devices that are not connected
        //       directly to this region by an implicit link
        return peers;
    }

    /**
     * Returns the subregions of the region in the specified layout.
     *
     * @param layout the layout being viewed
     * @return all regions that are "contained within" this layout's region
     */
    public Set<UiRegion> getSubRegions(UiTopoLayout layout) {
        Set<UiTopoLayout> kidLayouts = layoutService.getChildren(layout.id());
        Set<UiRegion> kids = new HashSet<>();
        kidLayouts.forEach(l -> kids.add(sharedModel.getRegion(l.regionId())));
        return kids;
    }

    /**
     * Returns the (synthetic) links of the region in the specified layout.
     *
     * @param layout the layout being viewed
     * @return all links that are contained by this layout's region
     */
    public List<UiSynthLink> getLinks(UiTopoLayout layout) {
        return sharedModel.getSynthLinks(layout.regionId());
    }

    /**
     * Refreshes the model's internal state.
     */
    public void refreshModel() {
        sharedModel.refresh();
    }

    /**
     * Navigates to the specified region by setting the associated layout as
     * current.
     *
     * @param regionId region identifier
     */
    public void navToRegion(String regionId) {
        // 1. find the layout corresponding to the region ID
        // 2. set this layout to be "current"
        RegionId r = RegionId.regionId(regionId);
        UiTopoLayout layout = layoutService.getLayout(r);
        setCurrentLayout(layout);
    }

    /**
     * Returns synthetic links that are in the current region, mapped by
     * original link ID.
     *
     * @return map of synth links
     */
    public Map<UiLinkId, UiSynthLink> relevantSynthLinks() {
        return sharedModel.relevantSynthLinks(currentLayout.regionId());
    }
}
