/*
 * Copyright 2018-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.openstacktelemetry.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.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.TpPort;
import org.onosproject.net.Host;
import org.onosproject.net.host.HostService;
import org.onosproject.openstacktelemetry.api.FlowInfo;
import org.onosproject.openstacktelemetry.api.StatsFlowRule;
import org.onosproject.openstacktelemetry.api.StatsFlowRuleAdminService;
import org.onosproject.openstacktelemetry.impl.DefaultStatsFlowRule;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiConnection;
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.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

import static org.onosproject.net.HostId.hostId;
import static org.onosproject.openstacktelemetry.util.OpenstackTelemetryUtil.getProtocolTypeFromString;

/**
 * Message handler for Openstack Telemetry view related messages.
 */
public class OpensteckTelemetryViewMessageHandler extends UiMessageHandler {
    private final Logger log = LoggerFactory.getLogger(getClass());

    // Chart View
    private static final String OST_DATA_REQ = "openstacktelemetryDataRequest";
    private static final String OST_DATA_RESP = "openstacktelemetryDataResponse";

    // Network Topology
    private static final String OST_IS_ACTIVATED_REQ = "openstackFlowStatsIsActivatedRequest";
    private static final String OST_IS_ACTIVATED_RESP = "openstackFlowStatsIsActivatedResponse";
    private static final String OST_FLOW_STATS_CREATE_REQ = "openstackFlowStatsCreateRequest";
    private static final String OST_FLOW_STATS_CREATE_RESP = "openstackFlowStatsCreateResponse";

    private static final String OSTS = "openstacktelemetrys";
    private static final String ANNOT_FLOW_IDS = "flowIds";
    private static final String ANNOT_PERIOD_OPTIONS = "periodOptions";

    private static final String SOURCE = "src";
    private static final String DESTINATION = "dst";
    private static final String SOURCE_IP = "srcIp";
    private static final String DESTINATION_IP = "dstIp";
    private static final String SOURCE_TRANSPORT_PORT = "srcPort";
    private static final String DESTINATION_TRANSPORT_PORT = "dstPort";
    private static final String SOURCE_HOST_NAME = "srcName";
    private static final String DESTINATION_HOST_NAME = "dstName";
    private static final String IP_PROTOCOL = "ipProto";
    private static final String IP_PROTOCOL_LIST = "ipProtoList";

    private static final String RESULT = "result";
    private static final String RESULT_OK = "OK";
    private static final String VALUE = "value";
    private static final String SUCCESS = "Success";
    private static final String FAILED = "Failed";
    private static final String FAILED_TO_CREATE_FLOW_STATS = "Failed to create a flow rule for statistics";

    private static final String[] IP_PROTOCOL_ARRAY = {"TCP", "UDP", "ANY"};

    private static final String STAT_CURR_ACC_PACKET = "curr_acc_packet";
    private static final String STAT_PREV_ACC_PACKET = "prev_acc_packet";
    private static final String STAT_CURR_ACC_BYTE = "curr_acc_byte";
    private static final String STAT_PREV_ACC_BYTE = "prev_acc_byte";
    private static final String STAT_ERROR_PACKET = "error_packet";
    private static final String STAT_DROP_PACKET = "drop_packet";

    private static final String CHART_TIME_FORMAT = "HH:mm:ss";

    // JSON node name
    private static final String JSON_NODE_FLOW = "flowOpt";
    private static final String JSON_NODE_PERIOD = "periodOpt";

    private static final String DEFAULT_PERIOD_OPTION_1MIN = "1 MIN";

    // Statistics period of statistics chart
    private static final Map<String, Integer> PERIOD_OPTION_MAP =
                            ImmutableMap.<String, Integer>builder()
                            .put(DEFAULT_PERIOD_OPTION_1MIN, 12)
                            .put("3 MIN", 36)
                            .put("5 MIN", 60)
                            .put("30 MIN", 360)
                            .put("1 HOUR", 720)
                            .put("2 HOUR", 1440)
                            .put("6 HOUR", 4320)
                            .put("24 HOUR", 17280)
                            .build();

    private HostService hostService;
    private StatsFlowRuleAdminService statsFlowRuleService;

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

        hostService = directory.get(HostService.class);
        statsFlowRuleService = directory.get(StatsFlowRuleAdminService.class);
    }

    @Override
    protected Collection<RequestHandler> createRequestHandlers() {
        return ImmutableSet.of(
                new ChartControlMessageRequest(),
                new FlowStatsIsActivatedRequestHandler(),
                new FlowStatsCreateRequestHandler()
        );
    }

    /* Handler for Line-Chart View */
    private final class ChartControlMessageRequest extends ChartRequestHandler {
        private Map<String, Queue<FlowInfo>> flowInfoMap = null;
        private String currentFlowKey = null;
        private String currentPeriod = DEFAULT_PERIOD_OPTION_1MIN;

        private ChartControlMessageRequest() {
            super(OST_DATA_REQ, OST_DATA_RESP, OSTS);
        }

        @Override
        protected String[] getSeries() {
            String[] series = {STAT_CURR_ACC_PACKET, STAT_PREV_ACC_PACKET,
                    STAT_CURR_ACC_BYTE, STAT_PREV_ACC_BYTE, STAT_ERROR_PACKET, STAT_DROP_PACKET};
            return series;
        }

        @Override
        protected void populateChart(ChartModel cm, ObjectNode payload) {
            if (statsFlowRuleService == null) {
                statsFlowRuleService = get(StatsFlowRuleAdminService.class);
            }
            if (flowInfoMap == null) {
                flowInfoMap = statsFlowRuleService.getFlowInfoMap();
            }

            String flowKey = string(payload, JSON_NODE_FLOW);
            String period = string(payload, JSON_NODE_PERIOD);

            if (!Strings.isNullOrEmpty(flowKey) || !Strings.isNullOrEmpty(period)) {
                if (!Strings.isNullOrEmpty(flowKey)) {
                    currentFlowKey = flowKey;
                }
                if (!Strings.isNullOrEmpty(period)) {
                    currentPeriod = period;
                }

                Queue<FlowInfo> flowInfoQ = flowInfoMap.get(currentFlowKey);

                if (flowInfoQ == null) {
                    log.warn("No such flow key {}", currentFlowKey);
                    return;
                } else {
                    populateMetrics(cm, flowInfoQ);
                    attachFlowList(cm);
                    attachPeriodList(cm);
                }
            } else {
                flowInfoMap.keySet().forEach(key -> {
                    Queue<FlowInfo> flowInfoQ = flowInfoMap.get(key);
                    if (flowInfoQ == null) {
                        log.warn("Key {} is not found in FlowInfoMap", key);
                        return;
                    }
                    FlowInfo flowInfo = getLatestFlowInfo(flowInfoQ);

                    Map<String, Object> local = Maps.newHashMap();
                    local.put(LABEL, key);
                    local.put(STAT_CURR_ACC_PACKET, flowInfo.statsInfo().currAccPkts());
                    local.put(STAT_PREV_ACC_PACKET, flowInfo.statsInfo().prevAccPkts());
                    local.put(STAT_CURR_ACC_BYTE, flowInfo.statsInfo().currAccBytes());
                    local.put(STAT_PREV_ACC_BYTE, flowInfo.statsInfo().prevAccBytes());
                    local.put(STAT_ERROR_PACKET, flowInfo.statsInfo().errorPkts());
                    local.put(STAT_DROP_PACKET, flowInfo.statsInfo().dropPkts());

                    populateMetric(cm.addDataPoint(key), local);
                });
            }
        }

        private void populateMetrics(ChartModel cm, Queue<FlowInfo> flowInfoQ) {
            FlowInfo[] flowInfos = flowInfoQ.toArray(new FlowInfo[flowInfoQ.size()]);
            SimpleDateFormat form = new SimpleDateFormat(CHART_TIME_FORMAT);
            int timeOffset = 0;
            Integer dataPointCount = PERIOD_OPTION_MAP.get(currentPeriod);
            if (dataPointCount != null) {
                timeOffset = flowInfos.length - (int) dataPointCount;
                if (timeOffset < 0) {
                    timeOffset = 0;
                }
            }

            for (int idx = timeOffset; idx < flowInfos.length; idx++) {
                Map<String, Object> local = Maps.newHashMap();
                local.put(LABEL, form.format(new Date(flowInfos[idx].statsInfo().fstPktArrTime())));
                local.put(STAT_CURR_ACC_PACKET, flowInfos[idx].statsInfo().currAccPkts());
                local.put(STAT_PREV_ACC_PACKET, flowInfos[idx].statsInfo().prevAccPkts());
                local.put(STAT_CURR_ACC_BYTE, flowInfos[idx].statsInfo().currAccBytes());
                local.put(STAT_PREV_ACC_BYTE, flowInfos[idx].statsInfo().prevAccBytes());
                local.put(STAT_ERROR_PACKET, flowInfos[idx].statsInfo().errorPkts());
                local.put(STAT_DROP_PACKET, flowInfos[idx].statsInfo().dropPkts());
                populateMetric(cm.addDataPoint(flowInfos[idx].uniqueFlowInfoKey()), local);
            }
        }

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

        private void attachFlowList(ChartModel cm) {
            ArrayNode array = arrayNode();
            flowInfoMap.keySet().forEach(key -> {
                array.add(key);
            });
            cm.addAnnotation(ANNOT_FLOW_IDS, array);
        }

        private void attachPeriodList(ChartModel cm) {
            ArrayNode array = arrayNode();
            PERIOD_OPTION_MAP.keySet().forEach(period -> {
                array.add(period);
            });
            cm.addAnnotation(ANNOT_PERIOD_OPTIONS, array);
        }

        private FlowInfo getLatestFlowInfo(Queue<FlowInfo> flowInfoQ) {
            FlowInfo[] flowInfos = flowInfoQ.toArray(new FlowInfo[flowInfoQ.size()]);
            return flowInfos[flowInfos.length - 1];
        }
    }

    /* Handler for Network Topology View */
    private final class FlowStatsIsActivatedRequestHandler extends RequestHandler {

        private FlowStatsIsActivatedRequestHandler() {
            super(OST_IS_ACTIVATED_REQ);
        }

        @Override
        public void process(ObjectNode payload) {
            String srcId = string(payload, SOURCE, null);
            String dstId = string(payload, DESTINATION, null);

            log.debug("Input from GUI: {}", payload.toString());
            if (srcId != null && dstId != null) {
                Host srcHost = hostService.getHost(hostId(srcId));
                Host dstHost = hostService.getHost(hostId(dstId));

                if (srcHost != null && dstHost != null) {
                    ArrayNode ipProtos = arrayNode();
                    String srcHostName = ipForHost(srcHost);
                    String dstHostName = ipForHost(dstHost);

                    for (String proto : IP_PROTOCOL_ARRAY) {
                        ipProtos.add(proto);
                    }

                    payload.put(SOURCE_HOST_NAME, srcHostName);
                    payload.put(DESTINATION_HOST_NAME, dstHostName);
                    payload.put(IP_PROTOCOL_LIST, ipProtos);

                    log.debug("Output to GUI: {}", payload.toString());

                    sendMessage(OST_IS_ACTIVATED_RESP, payload);
                }
            }
        }

        // Returns the first of the given host's set of IP addresses as a string.
        private String ipForHost(Host host) {
            Set<IpAddress> ipAddresses = host.ipAddresses();
            Iterator<IpAddress> it = ipAddresses.iterator();
            return it.hasNext() ? it.next().toString() + "/32" : "unknown";
        }
    }

    private final class FlowStatsCreateRequestHandler extends RequestHandler {
        private String srcIp;
        private String dstIp;
        private String ipProto;
        private String srcTpPort;
        private String dstTpPort;
        private ObjectNode result = objectNode();

        private FlowStatsCreateRequestHandler() {
            super(OST_FLOW_STATS_CREATE_REQ);
        }

        @Override
        public void process(ObjectNode payload) {
            srcIp = string(payload, SOURCE_IP, null);
            dstIp = string(payload, DESTINATION_IP, null);
            ipProto = string(payload, IP_PROTOCOL, null);
            srcTpPort = string(payload, SOURCE_TRANSPORT_PORT, null);
            dstTpPort = string(payload, DESTINATION_TRANSPORT_PORT, null);

            log.debug("[GUI input] srcIp:{} dstIp:{} ipPro:{} srcTpPort:{} dstTpPort:{}",
                     srcIp, dstIp, ipProto, srcTpPort, dstTpPort);

            try {
                StatsFlowRule statsFlowRule = DefaultStatsFlowRule.builder()
                        .srcIpPrefix(IpPrefix.valueOf(srcIp))
                        .dstIpPrefix(IpPrefix.valueOf(dstIp))
                        .srcTpPort(TpPort.tpPort(Integer.valueOf(srcTpPort)))
                        .dstTpPort(TpPort.tpPort(Integer.valueOf(dstTpPort)))
                        .ipProtocol(getProtocolTypeFromString(ipProto))
                        .build();
                statsFlowRuleService.createStatFlowRule(statsFlowRule);
                result.put(RESULT, SUCCESS);
                result.put(VALUE, RESULT_OK);
            } catch (Exception ex) {
                log.warn(FAILED_TO_CREATE_FLOW_STATS + " : " + ex.toString());
                result.put(RESULT, FAILED);
                result.put(VALUE, FAILED_TO_CREATE_FLOW_STATS);
            }
            sendMessage(OST_FLOW_STATS_CREATE_RESP, result);
        }
    }
}
