/*
 * Copyright 2016-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.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.onlab.util.Frequency;
import org.onlab.util.Spectrum;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
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;
import static org.onosproject.net.Device.Type;

/**
 * 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 ROADM_SHOW_ITEMS_REQ = "roadmShowFlowItemsRequest";
    private static final String ROADM_SHOW_ITEMS_RESP = "roadmShowFlowItemsResponse";

    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 CHANNEL_FREQUENCY = "channelFrequency";

    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,
            CHANNEL_FREQUENCY, CURRENT_POWER, ATTENUATION, HAS_ATTENUATION
    };

    private RoadmService roadmService;
    private DeviceService deviceService;
    private FlowRuleService flowRuleService;

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

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

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

    // 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 RoadmUtil.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, RoadmUtil.DEV_ID));
            // Update flows
            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);
            String spacing = RoadmUtil.NA, multiplier = RoadmUtil.NA, channelFrequency = "";
            OchSignal ochSignal = cd.ochSignal();
            if (ochSignal != null) {
                Frequency spacingFreq = ochSignal.channelSpacing().frequency();
                spacing = RoadmUtil.asGHz(spacingFreq);
                int spacingMult = ochSignal.spacingMultiplier();
                multiplier = String.valueOf(spacingMult);
                channelFrequency = String.format(" (%sGHz)",
                        RoadmUtil.asGHz(Spectrum.CENTER_FREQUENCY.add(spacingFreq.multiply(spacingMult))));
            }

            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, spacing)
                    .cell(CHANNEL_MULTIPLIER, multiplier)
                    .cell(CHANNEL_FREQUENCY, channelFrequency)
                    .cell(CURRENT_POWER, getCurrentPower(deviceId, cd))
                    .cell(HAS_ATTENUATION, hasAttenuation(deviceId, cd))
                    .cell(ATTENUATION, getAttenuation(deviceId, cd));
        }

        private String getCurrentPower(DeviceId deviceId, ChannelData channelData) {
            if (hasAttenuation(deviceId, channelData)) {
                // report channel power if channel exists
                Long currentPower = roadmService.getCurrentChannelPower(deviceId,
                        channelData.outPort(), channelData.ochSignal());
                return RoadmUtil.objectToString(currentPower, RoadmUtil.UNKNOWN);
            }
            // otherwise, report port power
            Type devType = deviceService.getDevice(deviceId).type();
            PortNumber port = devType == Type.FIBER_SWITCH ? channelData.inPort() : channelData.outPort();
            Long currentPower = roadmService.getCurrentPortPower(deviceId, port);
            return RoadmUtil.objectToString(currentPower, RoadmUtil.UNKNOWN);
        }

        private String getAttenuation(DeviceId deviceId, ChannelData channelData) {
            OchSignal signal = channelData.ochSignal();
            if (signal == null) {
                return RoadmUtil.NA;
            }
            Long attenuation = roadmService.getAttenuation(deviceId, channelData.outPort(), signal);
            return RoadmUtil.objectToString(attenuation, RoadmUtil.UNKNOWN);
        }

        private boolean hasAttenuation(DeviceId deviceId, ChannelData channelData) {
            OchSignal signal = channelData.ochSignal();
            if (signal == null) {
                return false;
            }
            return roadmService.attenuationRange(deviceId, channelData.outPort(), signal) != null;
        }
    }

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

        // 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, RoadmUtil.DEV_ID));
            FlowId flowId = FlowId.valueOf(number(payload, FLOW_ID));
            // Get connection information from the flow
            FlowEntry entry = findFlow(deviceId, flowId);
            if (entry == null) {
                log.error("Unable to find flow rule to set attenuation for device {}", deviceId);
                return;
            }
            ChannelData channelData = ChannelData.fromFlow(entry);
            PortNumber port = channelData.outPort();
            OchSignal signal = channelData.ochSignal();
            Range<Long> range = roadmService.attenuationRange(deviceId, port, signal);
            Long attenuation = payload.get(ATTENUATION).asLong();
            boolean validAttenuation = range != null && range.contains(attenuation);
            if (validAttenuation) {
                roadmService.setAttenuation(deviceId, port, signal, 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(RoadmUtil.VALID, validAttenuation);
            if (range  == null) {
                rootNode.put(RoadmUtil.MESSAGE, NO_ATTENUATION_MSG);
            } else {
                rootNode.put(RoadmUtil.MESSAGE, String.format(ATTENUATION_RANGE_MSG, range.toString()));
            }
            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, RoadmUtil.DEV_ID));
            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";

        // 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.";

        private CreateConnectionRequestHandler() {
            super(ROADM_CREATE_FLOW_REQ);
        }

        @Override
        public void process(ObjectNode payload) {
            DeviceId did = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
            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);
            long att = number(flowNode, ATTENUATION);

            boolean showItems = deviceService.getDevice(did).type() != Type.FIBER_SWITCH;
            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) {
                if (validChannel && channelAvailable) {
                    if (validAttenuation) {
                        roadmService.createConnection(did, priority, permanent, timeout, inPort, outPort, och, att);
                    } else {
                        roadmService.createConnection(did, priority, permanent, timeout, inPort, outPort, och);
                    }
                }
            }

            String channelMessage = "Invalid channel";
            String attenuationMessage = "Invalid attenuation";
            if (showItems) {
                // Construct error for 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
                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));
            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(RoadmUtil.VALID, result);
            if (!result) {
                // return error message to display if validation failed
                node.put(RoadmUtil.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());
        }
    }

    private final class CreateShowItemsRequestHandler extends RequestHandler {
        private static final String SHOW_CHANNEL = "showChannel";
        private static final String SHOW_ATTENUATION = "showAttenuation";
        private CreateShowItemsRequestHandler() {
            super(ROADM_SHOW_ITEMS_REQ);
        }

        @Override
        public void process(ObjectNode payload) {
            DeviceId did = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
            Type devType = deviceService.getDevice(did).type();
            // Build response
            ObjectNode node = objectNode();
            node.put(SHOW_CHANNEL, devType != Type.FIBER_SWITCH);
            node.put(SHOW_ATTENUATION, devType == Type.ROADM);
            sendMessage(ROADM_SHOW_ITEMS_RESP, node);
        }
    }
}
