/*
 * 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.driver.optical.power;

import java.util.List;
import java.util.Optional;

import com.google.common.collect.Range;
import org.onosproject.driver.extensions.OplinkAttenuation;
import org.onosproject.net.OchSignal;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.Direction;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.PowerConfig;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.OchSignalCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.instructions.ExtensionTreatment;
import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.optical.OpticalAnnotations;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.OpenFlowController;
import org.onosproject.openflow.controller.OpenFlowSwitch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Port Power (Gain and attenuation) implementation for Oplink 1-SLOT-8D ROADM.
 *
 * An Oplink ROADM port exposes OchSignal resources.
 * Optical Power can be set at port level or channel/wavelength level (attenuation).
 *
 */

public class OplinkRoadmPowerConfig extends AbstractHandlerBehaviour
                                    implements PowerConfig<Object> {

    private static final int LINE_IN = 1;
    private static final int LINE_OUT = 2;
    private static final int AUX_OUT_1 = 3;
    private static final int AUX_OUT_2 = 4;
    private static final int EXPRESS_OUT_1 = 5;
    private static final int EXPRESS_OUT_2 = 6;
    private static final int EXPRESS_OUT_3 = 7;
    private static final int EXPRESS_OUT_4 = 8;
    private static final int EXPRESS_OUT_5 = 9;
    private static final int EXPRESS_OUT_6 = 10;
    private static final int EXPRESS_OUT_7 = 11;
    private static final int AUX_IN_1 = 12;
    private static final int AUX_IN_2 = 13;
    private static final int EXPRESS_IN_1 = 14;
    private static final int EXPRESS_IN_2 = 15;
    private static final int EXPRESS_IN_3 = 16;
    private static final int EXPRESS_IN_4 = 17;
    private static final int EXPRESS_IN_5 = 18;
    private static final int EXPRESS_IN_6 = 19;
    private static final int EXPRESS_IN_7 = 20;

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

    // Component type
    private enum Type {
        NONE,
        PORT,
        CHANNEL
    }

    // Get the type if component is valid
    private Type getType(Object component) {
        if (component == null || component instanceof Direction) {
            return Type.PORT;
        } else if (component instanceof OchSignal) {
            return Type.CHANNEL;
        } else {
            return Type.NONE;
        }
    }

    private OpenFlowSwitch getOpenFlowDevice() {
        final OpenFlowController controller = this.handler().get(OpenFlowController.class);
        final Dpid dpid = Dpid.dpid(this.data().deviceId().uri());
        OpenFlowSwitch sw = controller.getSwitch(dpid);
        if (sw == null || !sw.isConnected()) {
            return null;
        } else {
            return sw;
        }
    }

    // Find matching flow on device
    private FlowEntry findFlow(PortNumber portNum, OchSignal och) {
        FlowRuleService service = this.handler().get(FlowRuleService.class);
        Iterable<FlowEntry> flowEntries = service.getFlowEntries(this.data().deviceId());

        // Return first matching flow
        for (FlowEntry entry : flowEntries) {
            TrafficSelector selector = entry.selector();
            OchSignalCriterion entrySigid =
                    (OchSignalCriterion) selector.getCriterion(Criterion.Type.OCH_SIGID);
            // Check channel
            if (entrySigid != null && och.equals(entrySigid.lambda())) {
                // Check input port
                PortCriterion entryPort =
                        (PortCriterion) selector.getCriterion(Criterion.Type.IN_PORT);
                if (entryPort != null && portNum.equals(entryPort.port())) {
                    return entry;
                }

                // Check output port
                TrafficTreatment treatment = entry.treatment();
                for (Instruction instruction : treatment.allInstructions()) {
                    if (instruction.type() == Instruction.Type.OUTPUT &&
                        ((Instructions.OutputInstruction) instruction).port().equals(portNum)) {
                        return entry;
                    }
                }
            }
        }
        log.warn("No matching flow found");
        return null;
    }

    @Override
    public Optional<Long> getTargetPower(PortNumber portNum, Object component) {
        Long returnVal = null;
        // Check if switch is connected, otherwise do not return value in store,
        // which is obsolete.
        if (getOpenFlowDevice() != null) {
            switch (getType(component)) {
                case PORT:
                    // Will be implemented in the future.
                    break;
                case CHANNEL:
                    returnVal = getChannelAttenuation(portNum, (OchSignal) component);
                    break;
                default:
                    break;
            }
        }
        return Optional.ofNullable(returnVal);
    }

    @Override
    public Optional<Long> currentPower(PortNumber portNum, Object component) {
        Long returnVal = null;
        // Check if switch is connected, otherwise do not return value in store,
        // which is obsolete.
        if (getOpenFlowDevice() != null) {
            switch (getType(component)) {
                case PORT:
                    returnVal = getCurrentPortPower(portNum);
                    break;
                case CHANNEL:
                    returnVal = getCurrentChannelPower(portNum, (OchSignal) component);
                    break;
                default:
                    break;
            }
        }
        return Optional.ofNullable(returnVal);
    }

    @Override
    public void setTargetPower(PortNumber portNum, Object component, long power) {
        if (getOpenFlowDevice() != null) {
            switch (getType(component)) {
                case PORT:
                    setTargetPortPower(portNum, power);
                    break;
                case CHANNEL:
                    setChannelAttenuation(portNum, (OchSignal) component, power);
                    break;
                default:
                    break;
            }
        } else {
            log.warn("OpenFlow handshaker driver not found or device is not connected");
        }
    }

    @Override
    public Optional<Range<Long>> getTargetPowerRange(PortNumber port, Object component) {
        Range<Long> range = null;
        switch (getType(component)) {
            case PORT:
                range = getTargetPortPowerRange(port);
                break;
            case CHANNEL:
                range = getChannelAttenuationRange(port);
                break;
            default:
                break;
        }
        return Optional.ofNullable(range);
    }

    @Override
    public Optional<Range<Long>> getInputPowerRange(PortNumber port, Object component) {
        Range<Long> range = null;
        switch (getType(component)) {
            case PORT:
                range = getInputPortPowerRange(port);
                break;
            default:
                break;
        }
        return Optional.ofNullable(range);
    }

    private Long getChannelAttenuation(PortNumber portNum, OchSignal och) {
        FlowEntry flowEntry = findFlow(portNum, och);
        if (flowEntry != null) {
            List<Instruction> instructions = flowEntry.treatment().allInstructions();
            for (Instruction ins : instructions) {
                if (ins.type() == Instruction.Type.EXTENSION) {
                    ExtensionTreatment ext = ((Instructions.ExtensionInstructionWrapper) ins).extensionInstruction();
                    if (ext.type() == ExtensionTreatmentType.ExtensionTreatmentTypes.OPLINK_ATTENUATION.type()) {
                        return (long) ((OplinkAttenuation) ext).getAttenuation();
                    }
                }
            }
        }
        return null;
    }

    private Long getCurrentPortPower(PortNumber portNum) {
        DeviceService deviceService = this.handler().get(DeviceService.class);
        Port port = deviceService.getPort(this.data().deviceId(), portNum);
        if (port != null) {
            String currentPower = port.annotations().value(OpticalAnnotations.CURRENT_POWER);
            if (currentPower != null) {
                return Long.valueOf(currentPower);
            }
        }
        return null;
    }

    private Long getCurrentChannelPower(PortNumber portNum, OchSignal och) {
        FlowEntry flowEntry = findFlow(portNum, och);
        if (flowEntry != null) {
            // TODO put somewhere else if possible
            // We put channel power in packets
            return flowEntry.packets();
        }
        return null;
    }

    private void setTargetPortPower(PortNumber portNum, long power) {
        OpenFlowSwitch device = getOpenFlowDevice();
        device.sendMsg(device.factory().buildOplinkPortPowerSet()
                .setXid(0)
                .setPort((int) portNum.toLong())
                .setPowerValue((int) power)
                .build());
    }

    private void setChannelAttenuation(PortNumber portNum, OchSignal och, long power) {
        FlowEntry flowEntry = findFlow(portNum, och);
        if (flowEntry != null) {
            List<Instruction> instructions = flowEntry.treatment().allInstructions();
            for (Instruction ins : instructions) {
                if (ins.type() == Instruction.Type.EXTENSION) {
                    ExtensionTreatment ext = ((Instructions.ExtensionInstructionWrapper) ins).extensionInstruction();
                    if (ext.type() == ExtensionTreatmentType.ExtensionTreatmentTypes.OPLINK_ATTENUATION.type()) {
                        ((OplinkAttenuation) ext).setAttenuation((int) power);
                        FlowRuleService service = this.handler().get(FlowRuleService.class);
                        service.applyFlowRules(flowEntry);
                        return;
                    }
                }
            }
            addAttenuation(flowEntry, power);
        } else {
            log.warn("Target channel power not set");
        }
    }

    // Replace flow with new flow containing Oplink attenuation extension instruction. Also resets
    // metrics.
    private void addAttenuation(FlowEntry flowEntry, long power) {
        FlowRule.Builder flowBuilder = new DefaultFlowRule.Builder();
        flowBuilder.withCookie(flowEntry.id().value());
        flowBuilder.withPriority(flowEntry.priority());
        flowBuilder.forDevice(flowEntry.deviceId());
        flowBuilder.forTable(flowEntry.tableId());
        if (flowEntry.isPermanent()) {
            flowBuilder.makePermanent();
        } else {
            flowBuilder.makeTemporary(flowEntry.timeout());
        }

        flowBuilder.withSelector(flowEntry.selector());

        // Copy original instructions and add attenuation instruction
        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
        flowEntry.treatment().allInstructions().forEach(ins -> treatmentBuilder.add(ins));
        treatmentBuilder.add(Instructions.extension(new OplinkAttenuation((int) power), this.data().deviceId()));
        flowBuilder.withTreatment(treatmentBuilder.build());

        FlowRuleService service = this.handler().get(FlowRuleService.class);
        service.applyFlowRules(flowBuilder.build());
    }

    // Returns the acceptable target range for an output Port, null otherwise
    private Range<Long> getTargetPortPowerRange(PortNumber port) {
        Range<Long> range = null;
        long num = port.toLong();
        if (num == LINE_OUT) {
            range = Range.closed(100L, 2040L);
        } else if (num >= AUX_OUT_1 && num <= EXPRESS_OUT_7) {
            range = Range.closed(-680L, 1530L);
        }
        return range;
    }

    // Returns the acceptable attenuation range for a connection (represented as
    // a flow with attenuation instruction). Port can be either the input or
    // output port of the connection. Returns null if the connection does not
    // support attenuation.
    private Range<Long> getChannelAttenuationRange(PortNumber port) {
        Range<Long> range = null;
        long num = port.toLong();
        // Only connections from AuxIn to LineOut or ExpressIn to LineOut support
        // attenuation.
        if (num == LINE_OUT ||
            num >= AUX_IN_1 && num <= EXPRESS_IN_7) {
            range = Range.closed(0L, 2550L);
        }
        return range;
    }

    // Returns the working input power range for an input port, null if the port
    // is not an input port.
    private Range<Long> getInputPortPowerRange(PortNumber port) {
        Range<Long> range = null;
        long portNum = port.toLong();
        if (portNum == LINE_IN) {
            // TODO implement support for IR and ER range
            // only supports LR right now
            range = Range.closed(-2600L, 540L);
        } else if (portNum == AUX_IN_1 || portNum == AUX_IN_2) {
            range = Range.closed(-1250L, 1590L);
        } else if (portNum >= EXPRESS_IN_1 && portNum <= EXPRESS_IN_7) {
            range = Range.closed(-1420L, 1420L);
        }
        return range;
    }
}
