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

import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.cluster.ClusterEvent;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.event.AbstractListenerRegistry;
import org.onosproject.event.EventDeliveryService;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.Device;
import org.onosproject.net.Host;
import org.onosproject.net.Link;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.link.LinkEvent;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_ADDED;
import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED;
import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
import static org.onosproject.ui.impl.topo.TopoUiEvent.Type.SUMMARY_UPDATE;


/**
 * Maintains a UI-centric model of the topology, as inferred from interactions
 * with the different (device, host, link, ...) services. Will serve up this
 * model to anyone who cares to {@link TopoUiListener listen}.
 */
@Component(immediate = true)
@Service
public class TopoUiModelManager implements TopoUiModelService {

    // TODO: put back to 30,000 ms for production
    private static final long SUMMARY_PERIOD = 15_000;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ClusterService clusterService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LinkService linkService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected HostService hostService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected MastershipService mastershipService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected IntentService intentService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowRuleService flowRuleService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected TopologyService topologyService;


    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected EventDeliveryService eventDispatcher;


    private AbstractListenerRegistry<TopoUiEvent, TopoUiListener>
            listenerRegistry = new AbstractListenerRegistry<>();


    private final TopoMessageFactory messageFactory = new TopoMessageFactory();
    private final MetaDb metaDb = new MetaDb();

    private final Timer timer = new Timer("topology-view");

    private TimerTask summaryTask = null;
    private boolean summaryRunning = false;


    @Activate
    public void activate() {
        eventDispatcher.addSink(TopoUiEvent.class, listenerRegistry);
        messageFactory.injectServices(
                metaDb,
                clusterService,
                deviceService,
                linkService,
                hostService,
                mastershipService
                // TODO: others??
        );
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        eventDispatcher.removeSink(TopoUiEvent.class);
        log.info("Stopped");
    }


    // TODO: figure out how to cull zombie listeners
    // The problem is when one refreshes the GUI (topology view)
    //  a new instance of AltTopoViewMessageHandler is created and added
    //  as a listener, but we never got a TopoStop event, which is what
    //  causes the listener (for an AltTopoViewMessageHandler instance) to
    //  be removed.
    // ==== Somehow need to tie this in to the GUI-disconnected event.
    //  This probably requires client-generated heartbeat messages to
    //  Keep the connection alive.


    @Override
    public void addListener(TopoUiListener listener) {
        listenerRegistry.addListener(listener);
    }

    @Override
    public void removeListener(TopoUiListener listener) {
        listenerRegistry.removeListener(listener);
    }

    @Override
    public List<ObjectNode> getInitialState() {
        List<ObjectNode> results = new ArrayList<>();
        addInstances(results);
        addDevices(results);
        addLinks(results);
        addHosts(results);
        return results;
    }

    @Override
    public synchronized void startSummaryMonitoring() {
        // first, cancel previous task if not canceled already
        stopSummaryMonitoring();

        // create and start a summary task, to execute with no delay, and
        // every SUMMARY_PERIOD milliseconds thereafter.
        summaryTask = new TimerTask() {
            @Override
            public void run() {
                if (summaryRunning) {
                    post(new TopoUiEvent(SUMMARY_UPDATE, null));
                }
            }
        };

        timer.schedule(summaryTask, 0, SUMMARY_PERIOD);
        summaryRunning = true;
    }

    @Override
    public synchronized void stopSummaryMonitoring() {
        if (summaryTask != null) {
            summaryTask.cancel();
            summaryTask = null;
        }
        summaryRunning = false;
    }

    @Override
    public SummaryData getSummaryData() {
        return new SummaryDataImpl();
    }

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

    private final class SummaryDataImpl implements SummaryData {
        private final Topology topology = topologyService.currentTopology();

        @Override
        public int deviceCount() {
            return topology.deviceCount();
        }

        @Override
        public int linkCount() {
            return topology.linkCount();
        }

        @Override
        public int hostCount() {
            return hostService.getHostCount();
        }

        @Override
        public int clusterCount() {
            return topology.clusterCount();
        }

        @Override
        public long intentCount() {
            return intentService.getIntentCount();
        }

        @Override
        public int flowRuleCount() {
            return flowRuleService.getFlowRuleCount();
        }
    }

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

    private static final Comparator<? super ControllerNode> NODE_COMPARATOR =
            (o1, o2) -> o1.id().toString().compareTo(o2.id().toString());

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

    private void addInstances(List<ObjectNode> results) {
        List<ControllerNode> nodes = new ArrayList<>(clusterService.getNodes());
        Collections.sort(nodes, NODE_COMPARATOR);
        for (ControllerNode node : nodes) {
            ClusterEvent ev = new ClusterEvent(INSTANCE_ADDED, node);
            results.add(messageFactory.instanceMessage(ev));
        }
    }

    private void addDevices(List<ObjectNode> results) {
        // Send optical first, others later -- for layered rendering
        List<DeviceEvent> deferred = new ArrayList<>();

        for (Device device : deviceService.getDevices()) {
            DeviceEvent ev = new DeviceEvent(DEVICE_ADDED, device);
            if (device.type() == Device.Type.ROADM) {
                results.add(messageFactory.deviceMessage(ev));
            } else {
                deferred.add(ev);
            }
        }

        for (DeviceEvent ev : deferred) {
            results.add(messageFactory.deviceMessage(ev));
        }
    }

    private void addLinks(List<ObjectNode> results) {
        // Send optical first, others later -- for layered rendering
        List<LinkEvent> deferred = new ArrayList<>();

        for (Link link : linkService.getLinks()) {
            LinkEvent ev = new LinkEvent(LINK_ADDED, link);
            if (link.type() == Link.Type.OPTICAL) {
                results.add(messageFactory.linkMessage(ev));
            } else {
                deferred.add(ev);
            }
        }

        for (LinkEvent ev : deferred) {
            results.add(messageFactory.linkMessage(ev));
        }
    }

    private void addHosts(List<ObjectNode> results) {
        for (Host host : hostService.getHosts()) {
            HostEvent ev = new HostEvent(HOST_ADDED, host);
            results.add(messageFactory.hostMessage(ev));
        }
    }

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

    private void post(TopoUiEvent event) {
        if (event != null) {
            eventDispatcher.post(event);
        }
    }

    // NOTE: session-independent state only
    // private inner classes to listen to device/host/link events
    // TODO..
}
