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

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Range;
import org.onlab.osgi.ServiceDirectory;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.DeviceId;
import org.onosproject.net.OchSignal;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowId;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiConnection;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.table.TableModel;
import org.onosproject.ui.table.TableRequestHandler;
import org.onosproject.ui.table.cell.HexLongFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Set;

import static org.onosproject.ui.JsonUtils.node;
import static org.onosproject.ui.JsonUtils.number;

/**
 * Table-View message handler for ROADM flow view.
 */
public class RoadmFlowViewMessageHandler extends UiMessageHandler {

    private static final String ROADM_FLOW_DATA_REQ = "roadmFlowDataRequest";
    private static final String ROADM_FLOW_DATA_RESP = "roadmFlowDataResponse";
    private static final String ROADM_FLOWS = "roadmFlows";

    private static final String ROADM_SET_ATTENUATION_REQ = "roadmSetAttenuationRequest";
    private static final String ROADM_SET_ATTENUATION_RESP = "roadmSetAttenuationResponse";

    private static final String ROADM_DELETE_FLOW_REQ = "roadmDeleteFlowRequest";

    private static final String ROADM_CREATE_FLOW_REQ = "roadmCreateFlowRequest";
    private static final String ROADM_CREATE_FLOW_RESP = "roadmCreateFlowResponse";

    private static final String NO_ROWS_MESSAGE = "No items found";

    private static final String DEV_ID = "devId";

    private static final String ID = "id";
    private static final String FLOW_ID = "flowId";
    private static final String APP_ID = "appId";
    private static final String GROUP_ID = "groupId";
    private static final String TABLE_ID = "tableId";
    private static final String PRIORITY = "priority";
    private static final String PERMANENT = "permanent";
    private static final String TIMEOUT = "timeout";
    private static final String STATE = "state";
    private static final String IN_PORT = "inPort";
    private static final String OUT_PORT = "outPort";
    private static final String CHANNEL_SPACING = "spacing";
    private static final String CHANNEL_MULTIPLIER = "multiplier";
    private static final String CURRENT_POWER = "currentPower";
    private static final String ATTENUATION = "attenuation";
    private static final String HAS_ATTENUATION = "hasAttenuation";

    private static final String[] COLUMN_IDS = {
            ID, FLOW_ID, APP_ID, GROUP_ID, TABLE_ID, PRIORITY, TIMEOUT,
            PERMANENT, STATE, IN_PORT, OUT_PORT, CHANNEL_SPACING,
            CHANNEL_MULTIPLIER, CURRENT_POWER, ATTENUATION, HAS_ATTENUATION
    };

    private static final String NA = "N/A";
    private static final String UNKNOWN = "Unknown";

    private static final long GHZ = 1_000_000_000L;

    private FlowRuleService flowRuleService;
    private RoadmService roadmService;

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

    @Override
    public void init(UiConnection connection, ServiceDirectory directory) {
        super.init(connection, directory);
        flowRuleService = get(FlowRuleService.class);
        roadmService = get(RoadmService.class);
    }

    @Override
    protected Collection<RequestHandler> createRequestHandlers() {
        return ImmutableSet.of(
                new FlowTableDataRequestHandler(),
                new SetAttenuationRequestHandler(),
                new DeleteConnectionRequestHandler(),
                new CreateConnectionRequestHandler()
        );
    }

    // Handler for sample table requests
    private final class FlowTableDataRequestHandler extends TableRequestHandler {

        private FlowTableDataRequestHandler() {
            super(ROADM_FLOW_DATA_REQ, ROADM_FLOW_DATA_RESP, ROADM_FLOWS);
        }

        @Override
        protected String[] getColumnIds() {
            return COLUMN_IDS;
        }

        @Override
        protected String noRowsMessage(ObjectNode payload) {
            return NO_ROWS_MESSAGE;
        }

        @Override
        protected TableModel createTableModel() {
            TableModel tm = super.createTableModel();
            tm.setFormatter(FLOW_ID, HexLongFormatter.INSTANCE);
            return tm;
        }

        @Override
        protected void populateTable(TableModel tm, ObjectNode payload) {
            DeviceId deviceId = DeviceId.deviceId(string(payload, DEV_ID, "(none)"));

            Iterable<FlowEntry> flowEntries = flowRuleService.getFlowEntries(deviceId);
            for (FlowEntry flowEntry : flowEntries) {
                populateRow(tm.addRow(), flowEntry, deviceId);
            }
        }

        private void populateRow(TableModel.Row row, FlowEntry entry, DeviceId deviceId) {
            ChannelData cd = ChannelData.fromFlow(entry);
            row.cell(ID, entry.id().value())
                    .cell(FLOW_ID, entry.id().value())
                    .cell(APP_ID, entry.appId())
                    .cell(PRIORITY, entry.priority())
                    .cell(TIMEOUT, entry.timeout())
                    .cell(PERMANENT, entry.isPermanent())
                    .cell(STATE, entry.state().toString())
                    .cell(IN_PORT, cd.inPort().toLong())
                    .cell(OUT_PORT, cd.outPort().toLong())
                    .cell(CHANNEL_SPACING, cd.ochSignal().channelSpacing().frequency().asHz() / GHZ)
                    .cell(CHANNEL_MULTIPLIER, cd.ochSignal().spacingMultiplier())
                    .cell(CURRENT_POWER, getCurrentPower(deviceId, cd))
                    .cell(ATTENUATION, getAttenuation(deviceId, cd));
        }

        private String getCurrentPower(DeviceId deviceId, ChannelData channelData) {
            Range<Long> range =
                    roadmService.attenuationRange(deviceId,
                                                  channelData.outPort(),
                                                  channelData.ochSignal());
            if (range != null) {
                Long currentPower =
                        roadmService.getCurrentChannelPower(deviceId,
                                                            channelData.outPort(),
                                                            channelData.ochSignal());
                if (currentPower != null) {
                    return String.valueOf(currentPower);
                }
            }
            return NA;
        }

        private String getAttenuation(DeviceId deviceId, ChannelData channelData) {
            Long attenuation =
                    roadmService.getAttenuation(deviceId, channelData.outPort(),
                                                channelData.ochSignal());
            if (attenuation != null) {
                return String.valueOf(attenuation);
            }
            return UNKNOWN;
        }
    }

    // Handler for setting attenuation
    private final class SetAttenuationRequestHandler extends RequestHandler {

        // Keys for response message
        private static final String VALID = "valid";
        private static final String MESSAGE = "message";

        // Error messages to display to user
        private static final String ATTENUATION_RANGE_MSG =
                "Attenuation must be in range %s.";
        private static final String NO_ATTENUATION_MSG =
                "Cannot set attenuation for this connection";

        private SetAttenuationRequestHandler() {
            super(ROADM_SET_ATTENUATION_REQ);
        }

        @Override
        public void process(ObjectNode payload) {
            DeviceId deviceId = DeviceId.deviceId(string(payload, DEV_ID, "(none)"));
            FlowId flowId = FlowId.valueOf(number(payload, FLOW_ID));
            long attenuation = payload.get(ATTENUATION).asLong();

            // Get connection information from the flow
            FlowEntry entry = findFlow(deviceId, flowId);
            if (entry == null) {
                log.error("Unable to find flow rule to set attenuation");
                return;
            }
            ChannelData cd = ChannelData.fromFlow(entry);
            Range<Long> range =
                    roadmService.attenuationRange(deviceId, cd.outPort(),
                                                  cd.ochSignal());

            boolean validAttenuation = (range != null && range.contains(attenuation));
            if (validAttenuation) {
                roadmService.setAttenuation(deviceId, cd.outPort(),
                                            cd.ochSignal(), attenuation);
            }

            ObjectNode rootNode = objectNode();
            // Send back flowId so view can identify which callback function to use
            rootNode.put(FLOW_ID, payload.get(FLOW_ID).asText());
            rootNode.put(VALID, validAttenuation);
            if (range != null) {
                rootNode.put(MESSAGE, String.format(ATTENUATION_RANGE_MSG,
                                                    range.toString()));
            } else {
                rootNode.put(MESSAGE, NO_ATTENUATION_MSG);
            }
            sendMessage(ROADM_SET_ATTENUATION_RESP, rootNode);
        }

        private FlowEntry findFlow(DeviceId deviceId, FlowId flowId) {
            for (FlowEntry entry : flowRuleService.getFlowEntries(deviceId)) {
                if (entry.id().equals(flowId)) {
                    return entry;
                }
            }
            return null;
        }
    }

    // Handler for deleting a connection
    private final class DeleteConnectionRequestHandler extends RequestHandler {
        private DeleteConnectionRequestHandler() {
            super(ROADM_DELETE_FLOW_REQ);
        }

        @Override
        public void process(ObjectNode payload) {
            DeviceId deviceId = DeviceId.deviceId(string(payload, DEV_ID, "(none)"));
            FlowId flowId = FlowId.valueOf(payload.get(ID).asLong());
            roadmService.removeConnection(deviceId, flowId);
        }
    }

    // Handler for creating a creating a connection from form data
    private final class CreateConnectionRequestHandler extends RequestHandler {

        // Keys to load from JSON
        private static final String FORM_DATA = "formData";
        private static final String CHANNEL_SPACING_INDEX = "index";
        private static final String INCLUDE_ATTENUATION = "includeAttenuation";

        // Keys for validation results
        private static final String CONNECTION = "connection";
        private static final String CHANNEL_AVAILABLE = "channelAvailable";

        // Error messages to display to user
        private static final String IN_PORT_ERR_MSG = "Invalid input port.";
        private static final String OUT_PORT_ERR_MSG = "Invalid output port.";
        private static final String CONNECTION_ERR_MSG =
                "Invalid connection from input port to output port.";
        private static final String CHANNEL_SPACING_ERR_MSG =
                "Channel spacing not supported.";
        private static final String CHANNEL_ERR_MSG =
                "Channel index must be in range %s.";
        private static final String CHANNEL_AVAILABLE_ERR_MSG =
                "Channel is already being used.";
        private static final String ATTENUATION_ERR_MSG =
                "Attenuation must be in range %s.";

        // Keys for validation object
        private static final String VALID = "valid";
        private static final String MESSAGE = "message";

        private CreateConnectionRequestHandler() {
            super(ROADM_CREATE_FLOW_REQ);
        }

        @Override
        public void process(ObjectNode payload) {
            DeviceId did = DeviceId.deviceId(string(payload, DEV_ID, "(none)"));
            ObjectNode flowNode = node(payload, FORM_DATA);
            int priority = (int) number(flowNode, PRIORITY);
            boolean permanent = bool(flowNode, PERMANENT);
            int timeout = (int) number(flowNode, TIMEOUT);
            PortNumber inPort = PortNumber.portNumber(number(flowNode, IN_PORT));
            PortNumber outPort = PortNumber.portNumber(number(flowNode, OUT_PORT));
            ObjectNode chNode = node(flowNode, CHANNEL_SPACING);
            ChannelSpacing spacing =
                    channelSpacing((int) number(chNode, CHANNEL_SPACING_INDEX));
            int multiplier = (int) number(flowNode, CHANNEL_MULTIPLIER);
            OchSignal och = OchSignal.newDwdmSlot(spacing, multiplier);
            boolean includeAttenuation = bool(flowNode, INCLUDE_ATTENUATION);
            long att = number(flowNode, ATTENUATION);

            boolean validInPort = roadmService.validInputPort(did, inPort);
            boolean validOutPort = roadmService.validOutputPort(did, outPort);
            boolean validConnect = roadmService.validConnection(did, inPort, outPort);
            boolean validSpacing = true;
            boolean validChannel = roadmService.validChannel(did, inPort, och);
            boolean channelAvailable = roadmService.channelAvailable(did, och);
            boolean validAttenuation = roadmService.attenuationInRange(did, outPort, att);

            if (validConnect && validChannel && channelAvailable) {
                if (includeAttenuation && validAttenuation) {
                    roadmService.createConnection(did, priority, permanent,
                                                  timeout, inPort, outPort,
                                                  och, att);
                } else if (!includeAttenuation) {
                    roadmService.createConnection(did, priority, permanent,
                                                  timeout, inPort, outPort,
                                                  och);
                }
            }

            // Construct error for channel
            String channelMessage = "Invalid channel";
            if (!validChannel) {
                Set<OchSignal> lambdas = roadmService.queryLambdas(did, outPort);
                if (lambdas != null) {
                    Range<Integer> range = channelRange(lambdas);
                    if (range.contains(och.spacingMultiplier())) {
                        // Channel spacing error
                        validSpacing = false;
                    } else {
                        channelMessage = String.format(CHANNEL_ERR_MSG, range.toString());
                    }
                }
            }

            // Construct error for attenuation
            String attenuationMessage = "Invalid attenuation";
            if (!validAttenuation) {
                Range<Long> range =
                        roadmService.attenuationRange(did, outPort, och);
                if (range != null) {
                    attenuationMessage =
                            String.format(ATTENUATION_ERR_MSG, range.toString());
                }
            }

            // Build response
            ObjectNode node = objectNode();

            node.set(IN_PORT, validationObject(validInPort, IN_PORT_ERR_MSG));
            node.set(OUT_PORT, validationObject(validOutPort, OUT_PORT_ERR_MSG));
            node.set(CONNECTION, validationObject(validConnect, CONNECTION_ERR_MSG));
            node.set(CHANNEL_SPACING, validationObject(validChannel || validSpacing,
                                                       CHANNEL_SPACING_ERR_MSG));
            node.set(CHANNEL_MULTIPLIER, validationObject(validChannel || !validSpacing,
                                                          channelMessage));
            node.set(CHANNEL_AVAILABLE, validationObject(!validChannel || channelAvailable,
                                                         CHANNEL_AVAILABLE_ERR_MSG));
            node.set(ATTENUATION, validationObject(validAttenuation, attenuationMessage));
            node.put(INCLUDE_ATTENUATION, includeAttenuation);

            sendMessage(ROADM_CREATE_FLOW_RESP, node);
        }

        // Returns the ChannelSpacing based on the selection made
        private ChannelSpacing channelSpacing(int selectionIndex) {
            switch (selectionIndex) {
                case 0: return ChannelSpacing.CHL_100GHZ;
                case 1: return ChannelSpacing.CHL_50GHZ;
                case 2: return ChannelSpacing.CHL_25GHZ;
                case 3: return ChannelSpacing.CHL_12P5GHZ;
                // 6.25GHz cannot be used with ChannelSpacing.newDwdmSlot
                // case 4: return ChannelSpacing.CHL_6P25GHZ;
                default: return ChannelSpacing.CHL_50GHZ;
            }
        }

        // Construct validation object to return to the view
        private ObjectNode validationObject(boolean result, String message) {
            ObjectNode node = objectNode();
            node.put(VALID, result);
            if (!result) {
                // return error message to display if validation failed
                node.put(MESSAGE, message);
            }
            return node;
        }

        // Returns the minimum and maximum channel spacing
        private Range<Integer> channelRange(Set<OchSignal> signals) {
            Comparator<OchSignal> compare =
                    (OchSignal a, OchSignal b) -> a.spacingMultiplier() - b.spacingMultiplier();
            OchSignal minOch = Collections.min(signals, compare);
            OchSignal maxOch = Collections.max(signals, compare);
            return Range.closed(minOch.spacingMultiplier(), maxOch.spacingMultiplier());
        }
    }
}
