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

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableSet;
import org.onosproject.net.driver.Behaviour;
import org.onosproject.net.driver.Driver;
import org.onosproject.net.driver.DriverService;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiMessageHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Message handler for driver matrix view related messages.
 */
public class DriverViewMessageHandler extends UiMessageHandler {

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

    private static final int ONE = 1;
    private static final String DRIVER_DATA_REQUEST = "driverDataRequest";
    private static final String DRIVER_DATA_RESPONSE = "driverDataResponse";

    private static final String DRIVERS = "drivers";
    private static final String BEHAVIOURS = "behaviours";
    private static final String MATRIX = "matrix";

    private static final Comparator<? super Class<? extends Behaviour>> BEHAVIOUR_BY_NAME =
            (o1, o2) -> o1.getSimpleName().compareTo(o2.getSimpleName());
    private static final Comparator<? super Driver> DRIVER_BY_NAME =
            (o1, o2) -> o1.name().compareTo(o2.name());


    @Override
    protected Collection<RequestHandler> createRequestHandlers() {
        return ImmutableSet.of(
                new DataRequestHandler()
                // TODO: for row selection, produce data for detail panel
//                new DetailRequestHandler()
        );
    }

    // handler for driver matrix requests
    private final class DataRequestHandler extends RequestHandler {

        private DataRequestHandler() {
            super(DRIVER_DATA_REQUEST);
        }

        @Override
        public void process(long sid, ObjectNode payload) {
            DriverService driverService = get(DriverService.class);

            List<Driver> drivers = new ArrayList<>(driverService.getDrivers());
            drivers = orderDrivers(drivers);

            // Produce a union of all behaviours (and order them)
            List<Class<? extends Behaviour>> behaviours = orderBehaviours(drivers);

            // Produce a JSON structure and send it
            sendMessage(DRIVER_DATA_RESPONSE, 0, driversJson(drivers, behaviours));
        }

        private List<Driver> orderDrivers(List<Driver> drivers) {
            // For now order by alphanumeric name of the driver
            drivers.sort(DRIVER_BY_NAME);
            return drivers;
        }

        private List<Class<? extends Behaviour>> orderBehaviours(List<Driver> drivers) {
            // first, produce a set-union of all behaviours from all drivers...
            Set<Class<? extends Behaviour>> allBehaviours = new HashSet<>();
            drivers.forEach(d -> allBehaviours.addAll(d.behaviours()));

            // for now, order by alphanumeric name of the abstract behaviour simple name
            List<Class<? extends Behaviour>> ordered = new ArrayList<>(allBehaviours);
            ordered.sort(BEHAVIOUR_BY_NAME);
            return ordered;
        }

        private ObjectNode driversJson(List<Driver> drivers,
                                       List<Class<? extends Behaviour>> behaviours) {
            ObjectNode root = objectNode();
            addBehaviours(root, behaviours);
            addDrivers(root, drivers);
            addMatrixCells(root, drivers);
            return root;
        }

        private void addBehaviours(ObjectNode root,
                                   List<Class<? extends Behaviour>> behaviours) {
            ArrayNode array = arrayNode();
            root.set(BEHAVIOURS, array);
            behaviours.forEach(b -> array.add(b.getSimpleName()));
        }

        private void addDrivers(ObjectNode root, List<Driver> drivers) {
            ArrayNode array = arrayNode();
            root.set(DRIVERS, array);
            drivers.forEach(d -> array.add(d.name()));
        }

        private Set<Driver> findLineage(Driver driver) {
            ImmutableSet.Builder<Driver> lineage = ImmutableSet.builder();
            lineage.add(driver);
            List<Driver> parents = driver.parents();
            if (parents != null) {
                parents.forEach(p -> lineage.addAll(findLineage(p)));
            }
            return lineage.build();
        }

        private void addMatrixCells(ObjectNode root, List<Driver> drivers) {
            ObjectNode matrix = objectNode();
            root.set(MATRIX, matrix);

            drivers.forEach(driver -> {
                ObjectNode dnode = objectNode();
                matrix.set(driver.name(), dnode);
                Set<Driver> lineage = findLineage(driver);
                lineage.forEach(d -> d.behaviours().forEach(b -> {
                    // TODO: can put a payload here, rather than a '1' marker
                    dnode.put(b.getSimpleName(), ONE);
                }));
            });
        }
    }
}
