/*
 * 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.cpman.gui;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.LocalDateTime;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cpman.ControlLoadSnapshot;
import org.onosproject.cpman.ControlMetricType;
import org.onosproject.cpman.ControlPlaneMonitorService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.chart.ChartModel;
import org.onosproject.ui.chart.ChartRequestHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.LongStream;

import static org.onosproject.cpman.ControlResource.CONTROL_MESSAGE_METRICS;
import static org.onosproject.cpman.ControlResource.Type.CONTROL_MESSAGE;

/**
 * Message handler for control plane monitoring view related messages.
 */
public class CpmanViewMessageHandler extends UiMessageHandler {

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

    private static final String CPMAN_DATA_REQ = "cpmanDataRequest";
    private static final String CPMAN_DATA_RESP = "cpmanDataResponse";
    private static final String CPMANS = "cpmans";

    private static final String DEVICE_IDS = "deviceIds";

    // TODO: we assume that server side always returns 20 data points
    // to feed 20 minutes time slots, later this should make to be configurable
    private static final int NUM_OF_DATA_POINTS = 20;

    private static final int MILLI_CONV_UNIT = 1000;

    private static final String TIME_FORMAT = "HH:mm";

    private long timestamp = 0L;

    @Override
    protected Collection<RequestHandler> createRequestHandlers() {
        return ImmutableSet.of(
                new ControlMessageRequest()
        );
    }

    private final class ControlMessageRequest extends ChartRequestHandler {

        private ControlMessageRequest() {
            super(CPMAN_DATA_REQ, CPMAN_DATA_RESP, CPMANS);
        }

        @Override
        protected String[] getSeries() {
            return CONTROL_MESSAGE_METRICS.stream().map(type ->
                    StringUtils.lowerCase(type.name())).toArray(String[]::new);
        }

        @Override
        protected void populateChart(ChartModel cm, ObjectNode payload) {
            String uri = string(payload, "devId");
            ControlPlaneMonitorService cpms = get(ControlPlaneMonitorService.class);
            ClusterService cs = get(ClusterService.class);
            DeviceService ds = get(DeviceService.class);

            if (!Strings.isNullOrEmpty(uri)) {
                DeviceId deviceId = DeviceId.deviceId(uri);
                if (cpms.availableResources(CONTROL_MESSAGE).contains(deviceId.toString())) {
                    Map<ControlMetricType, Long[]> data = generateMatrix(cpms, cs, deviceId);
                    LocalDateTime ldt = new LocalDateTime(timestamp * MILLI_CONV_UNIT);

                    populateMetrics(cm, data, ldt, NUM_OF_DATA_POINTS);

                    Set<DeviceId> deviceIds = Sets.newHashSet();
                    ds.getAvailableDevices().forEach(device -> deviceIds.add(device.id()));
                    attachDeviceList(cm, deviceIds);
                }
            } else {
                Set<String> deviceIds = cpms.availableResources(CONTROL_MESSAGE);
                for (String deviceId : deviceIds) {
                    Map<ControlMetricType, Long> data =
                            populateDeviceMetrics(cpms, cs, DeviceId.deviceId(deviceId));
                    Map<String, Object> local = Maps.newHashMap();
                    for (ControlMetricType cmt : CONTROL_MESSAGE_METRICS) {
                        local.put(StringUtils.lowerCase(cmt.name()), data.get(cmt));
                    }

                    local.put(LABEL, deviceId);
                    populateMetric(cm.addDataPoint(deviceId), local);
                }
            }
        }

        private Map<ControlMetricType, Long> populateDeviceMetrics(ControlPlaneMonitorService cpms,
                                                                   ClusterService cs, DeviceId deviceId) {
            Map<ControlMetricType, Long> data = Maps.newHashMap();
            for (ControlMetricType cmt : CONTROL_MESSAGE_METRICS) {
                ControlLoadSnapshot cls;
                try {
                    cls = cpms.getLoad(cs.getLocalNode().id(),
                            cmt, NUM_OF_DATA_POINTS, TimeUnit.MINUTES,
                            Optional.of(deviceId)).get();
                    data.put(cmt, Math.round(LongStream.of(cls.recent()).average().getAsDouble()));
                    timestamp = cls.time();
                } catch (InterruptedException | ExecutionException e) {
                    log.warn(e.getMessage());
                }
            }
            return data;
        }

        private Map<ControlMetricType, Long[]> generateMatrix(ControlPlaneMonitorService cpms,
                                                              ClusterService cs, DeviceId deviceId) {
            Map<ControlMetricType, Long[]> data = Maps.newHashMap();
            for (ControlMetricType cmt : CONTROL_MESSAGE_METRICS) {
                ControlLoadSnapshot cls;
                try {
                    cls = cpms.getLoad(cs.getLocalNode().id(),
                            cmt, NUM_OF_DATA_POINTS, TimeUnit.MINUTES,
                            Optional.of(deviceId)).get();

                    // TODO: in some cases, the number of returned dataset is
                    // less than what we expected (expected -1)
                    // As a workaround, we simply fill the slot with 0 values,
                    // such a bug should be fixed with updated RRD4J lib...
                    data.put(cmt, ArrayUtils.toObject(fillData(cls.recent(), NUM_OF_DATA_POINTS)));
                    timestamp = cls.time();
                } catch (InterruptedException | ExecutionException e) {
                    log.warn(e.getMessage());
                }
            }
            return data;
        }

        private long[] fillData(long[] origin, int expected) {
            if (origin.length == expected) {
                return origin;
            } else {
                long[] filled = new long[expected];
                for (int i = 0; i < expected; i++) {
                    if (i == 0) {
                        filled[i] = 0;
                    } else {
                        filled[i] = origin[i - 1];
                    }
                }
                return filled;
            }
        }

        private void populateMetrics(ChartModel cm,
                                     Map<ControlMetricType, Long[]> data,
                                     LocalDateTime time, int numOfDp) {
            for (int i = 0; i < numOfDp; i++) {
                Map<String, Object> local = Maps.newHashMap();
                for (ControlMetricType cmt : CONTROL_MESSAGE_METRICS) {
                    local.put(StringUtils.lowerCase(cmt.name()), data.get(cmt)[i]);
                }

                String calculated = time.minusMinutes(numOfDp - i).toString(TIME_FORMAT);

                local.put(LABEL, calculated);
                populateMetric(cm.addDataPoint(calculated), local);
            }
        }

        private void populateMetric(ChartModel.DataPoint dataPoint,
                                    Map<String, Object> data) {
            data.forEach(dataPoint::data);
        }

        private void attachDeviceList(ChartModel cm, Set<DeviceId> deviceIds) {
            ArrayNode array = arrayNode();
            deviceIds.forEach(id -> array.add(id.toString()));
            cm.addAnnotation(DEVICE_IDS, array);
        }
    }
}
