/*
 * 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.concurrent.atomic.AtomicInteger;
import java.util.List;

import com.google.common.collect.Range;

import org.onosproject.driver.extensions.OplinkAttenuation;
import org.onosproject.net.OchSignal;
import org.onosproject.net.Direction;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.HandlerBehaviour;
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.OpenFlowOpticalSwitch;
import org.onosproject.openflow.controller.OpenFlowSwitch;
import org.onosproject.openflow.controller.PortDescPropertyType;
import org.projectfloodlight.openflow.protocol.OFObject;
import org.projectfloodlight.openflow.protocol.OFPortOptical;

import org.slf4j.Logger;

import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.net.Device.Type;

/**
 * Oplink power config utility.
 */
public class OplinkPowerConfigUtil {

    // Parent driver handler behaviour
    private HandlerBehaviour behaviour;
    // Transaction id to use.
    private final AtomicInteger xidCounter = new AtomicInteger(0);
    // Log
    private final Logger log = getLogger(getClass());

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

    // Port properties for oplink devices, currently supports EDFA and ROADM.
    // This type is mapped to OFPortDescPropOpticalTransport#getPortType() value.
    private enum PortDescType {
        NONE,
        PA_LINE_IN,
        PA_LINE_OUT,
        BA_LINE_IN,
        BA_LINE_OUT,
        EXP_IN,
        EXP_OUT,
        AUX_IN,
        AUX_OUT,
    }

    /**
     * Power threshold of each port, in 0.01 dB
     * Note:
     * These threshold configurations are just in use for a short time.
     * In the future, the power threshold would be obtained from physical device.
     */
    // EDFA
    private static final long EDFA_POWER_IN_WEST_LOW_THRES = -1900L;
    private static final long EDFA_POWER_IN_WEST_HIGH_THRES = 0L;
    private static final long EDFA_POWER_IN_EAST_LOW_THRES = -3100L;
    private static final long EDFA_POWER_IN_EAST_HIGH_THRES = 700L;
    private static final long EDFA_POWER_OUT_LOW_THRES = 0L;
    private static final long EDFA_POWER_OUT_HIGH_THRES = 1900L;
    // ROADM
    private static final long ROADM_POWER_LINE_IN_LOW_THRES = -3000L;
    private static final long ROADM_POWER_LINE_IN_HIGH_THRES = 2350L;
    private static final long ROADM_POWER_LINE_OUT_LOW_THRES = 0L;
    private static final long ROADM_POWER_LINE_OUT_HIGH_THRES = 2350L;
    private static final long ROADM_POWER_OTHER_IN_LOW_THRES = -1500L;
    private static final long ROADM_POWER_OTHER_IN_HIGH_THRES = 2000L;
    private static final long ROADM_POWER_OTHER_OUT_LOW_THRES = -600L;
    private static final long ROADM_POWER_OTHER_OUT_HIGH_THRES = 1500L;
    private static final long ROADM_MIN_ATTENUATION = 0L;
    private static final long ROADM_MAX_ATTENUATION = 2500L;

    /**
     * Create a new OplinkPowerConfigUtil.
     * @param behaviour driver handler behaviour
     */
    public OplinkPowerConfigUtil(HandlerBehaviour behaviour) {
        this.behaviour = behaviour;
    }

    /**
     * Obtains specified port/channel target power.
     *
     * @param port the port number
     * @param component the port component
     * @return target power value in .01 dBm
     */
    public Long getTargetPower(PortNumber port, Object component) {
        switch (getComponentType(component)) {
            case PORT:
                return getPortPower(port, OpticalAnnotations.TARGET_POWER);
            case CHANNEL:
                return getChannelAttenuation(port, (OchSignal) component);
            default:
                return null;
        }
    }

    /**
     * Obtains specified port/channel current power.
     *
     * @param port the port number
     * @param component the port component
     * @return current power value in .01 dBm
     */
    public Long getCurrentPower(PortNumber port, Object component) {
        switch (getComponentType(component)) {
            case PORT:
                return getPortPower(port, OpticalAnnotations.CURRENT_POWER);
            case CHANNEL:
                return getCurrentChannelPower(port, (OchSignal) component);
            default:
                return null;
        }
    }

    /**
     * Sets specified port target power or channel attenuation.
     *
     * @param port the port number
     * @param component the port component
     * @param power target power in .01 dBm
     */
    public void setTargetPower(PortNumber port, Object component, long power) {
        switch (getComponentType(component)) {
            case PORT:
                setPortPower(port, power);
                break;
            case CHANNEL:
                setChannelAttenuation(port, (OchSignal) component, power);
               break;
            default:
                break;
        }
    }

    /**
     * Returns the acceptable target range for an output port/channel, null otherwise.
     *
     * @param port the port number
     * @param component the port component
     * @return power range
     */
    public Range<Long> getTargetPowerRange(PortNumber port, Object component) {
        switch (getComponentType(component)) {
            case PORT:
                return getTargetPortPowerRange(port);
            case CHANNEL:
                return getChannelAttenuationRange(port);
            default:
                return null;
        }
    }

    /**
     * Returns the working input power range for an input port, null otherwise.
     *
     * @param port the port number
     * @param component the port component
     * @return power range
     */
    public Range<Long> getInputPowerRange(PortNumber port, Object component) {
        switch (getComponentType(component)) {
            case PORT:
                return getInputPortPowerRange(port);
            default:
                return null;
        }
    }

    /**
     * Returns specified component type.
     *
     * @param component the port component
     * @return component type
     */
    private ComponentType getComponentType(Object component) {
        if (component == null || component instanceof Direction) {
            return ComponentType.PORT;
        } else if (component instanceof OchSignal) {
            return ComponentType.CHANNEL;
        }
        return ComponentType.NONE;
    }

    /**
     * Returns current switch known to this OF controller.
     *
     * @return current switch
     */
    private OpenFlowSwitch getOpenFlowDevice() {
        final DriverHandler handler = behaviour.handler();
        final OpenFlowController controller = handler.get(OpenFlowController.class);
        final Dpid dpid = Dpid.dpid(handler.data().deviceId().uri());
        OpenFlowSwitch sw = controller.getSwitch(dpid);
        if (sw == null || !sw.isConnected()) {
            log.warn("OpenFlow handshaker driver not found or device is not connected, dpid = {}", dpid);
            return null;
        }
        return sw;
    }

    /**
     * Find oplink port description type from optical ports.
     *
     * @param opsw switch
     * @param portNum the port number
     * @return port oplink port description type
     */
    private PortDescType getPortDescType(OpenFlowOpticalSwitch opsw, PortNumber portNum) {
        for (PortDescPropertyType type : opsw.getPortTypes()) {
            List<? extends OFObject> portsOf = opsw.getPortsOf(type);
            for (OFObject op : portsOf) {
                if (op instanceof OFPortOptical) {
                    OFPortOptical opticalPort = (OFPortOptical) op;
                    if ((long) opticalPort.getPortNo().getPortNumber() == portNum.toLong()) {
                        return PortDescType.values()[opticalPort.getDesc().get(0).getPortType()];
                    }
                }
            }
        }
        return PortDescType.NONE;
    }

    /**
     * Returns the target port power range.
     *
     * @param portNum the port number
     * @return power range
     */
    private Range<Long> getTargetPortPowerRange(PortNumber portNum) {
        OpenFlowSwitch ofs = getOpenFlowDevice();
        if (ofs == null) {
            return null;
        }
        PortDescType portType = getPortDescType((OpenFlowOpticalSwitch) ofs, portNum);
        Type devType = ofs.deviceType();
        // FIXME
        // Short time hard code.
        // The power range will be obtained from physical device in the future.
        switch (devType) {
            case OPTICAL_AMPLIFIER:
                if (portType == PortDescType.PA_LINE_OUT || portType == PortDescType.BA_LINE_OUT) {
                    return Range.closed(EDFA_POWER_OUT_LOW_THRES, EDFA_POWER_OUT_HIGH_THRES);
                }
                break;
            case ROADM:
                if (portType == PortDescType.PA_LINE_OUT) {
                    return Range.closed(ROADM_POWER_LINE_OUT_LOW_THRES, ROADM_POWER_LINE_OUT_HIGH_THRES);
                } else if (portType == PortDescType.EXP_OUT || portType == PortDescType.AUX_OUT) {
                    return Range.closed(ROADM_POWER_OTHER_OUT_LOW_THRES, ROADM_POWER_OTHER_OUT_HIGH_THRES);
                }
                break;
            default:
                log.warn("Unexpected device type: {}", devType);
                break;
        }
        // Unexpected port or device type. Do not need warning here for port polling.
        return null;
    }

    /**
     * Returns the input port power range.
     *
     * @param portNum the port number
     * @return power range
     */
    private Range<Long> getInputPortPowerRange(PortNumber portNum) {
        OpenFlowSwitch ofs = getOpenFlowDevice();
        if (ofs == null) {
            return null;
        }
        PortDescType portType = getPortDescType((OpenFlowOpticalSwitch) ofs, portNum);
        Type devType = ofs.deviceType();
        // FIXME
        // Short time hard code.
        // The port type and power range will be obtained from physical device in the future.
        switch (devType) {
            case OPTICAL_AMPLIFIER:
                if (portType == PortDescType.PA_LINE_IN) {
                    return Range.closed(EDFA_POWER_IN_WEST_LOW_THRES, EDFA_POWER_IN_WEST_HIGH_THRES);
                } else if (portType == PortDescType.BA_LINE_IN) {
                    return Range.closed(EDFA_POWER_IN_EAST_LOW_THRES, EDFA_POWER_IN_EAST_HIGH_THRES);
                }
                break;
            case ROADM:
                if (portType == PortDescType.PA_LINE_IN) {
                    return Range.closed(ROADM_POWER_LINE_IN_LOW_THRES, ROADM_POWER_LINE_IN_HIGH_THRES);
                } else if (portType == PortDescType.EXP_IN || portType == PortDescType.AUX_IN) {
                    return Range.closed(ROADM_POWER_OTHER_IN_LOW_THRES, ROADM_POWER_OTHER_IN_HIGH_THRES);
                }
                break;
            default:
                log.warn("Unexpected device type: {}", devType);
                break;
        }
        // Unexpected port or device type. Do not need warning here for port polling.
        return null;
    }

    /**
     * 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.
     *
     * @param portNum the port number
     * @return attenuation range
     */
    private Range<Long> getChannelAttenuationRange(PortNumber portNum) {
        OpenFlowSwitch ofs = getOpenFlowDevice();
        if (ofs == null) {
            return null;
        }
        if (ofs.deviceType() != Type.ROADM) {
            return null;
        }
        PortDescType portType = getPortDescType((OpenFlowOpticalSwitch) ofs, portNum);
        // Short time hard code.
        // The port type and attenuation range will be obtained from physical device in the future.
        if (portType == PortDescType.PA_LINE_OUT || portType == PortDescType.EXP_IN ||
                portType == PortDescType.AUX_IN) {
            return Range.closed(ROADM_MIN_ATTENUATION, ROADM_MAX_ATTENUATION);
        }
        // Unexpected port. Do not need warning here for port polling.
        return null;
    }

    /**
     * Find specified port power from port description.
     *
     * @param portNum the port number
     * @param annotation annotation in port description
     * @return power value in 0.01 dBm
     */
    private Long getPortPower(PortNumber portNum, String annotation) {
        // Check if switch is connected, otherwise do not return value in store, which is obsolete.
        if (getOpenFlowDevice() == null) {
            // Warning already exists in method getOpenFlowDevice()
            return null;
        }
        final DriverHandler handler = behaviour.handler();
        DeviceService deviceService = handler.get(DeviceService.class);
        Port port = deviceService.getPort(handler.data().deviceId(), portNum);
        if (port == null) {
            log.warn("Unexpected port: {}", portNum);
            return null;
        }
        String power = port.annotations().value(annotation);
        if (power == null) {
            log.warn("Cannot get {} from port {}.", annotation, portNum);
            return null;
        }
        return Long.valueOf(power);
    }

    /**
     * Sets specified port power value.
     *
     * @param portNum the port number
     * @param power power value
     */
    private void setPortPower(PortNumber portNum, long power) {
        OpenFlowSwitch device = getOpenFlowDevice();
        // Check if switch is connected
        if (device == null) {
            return;
        }
        device.sendMsg(device.factory().buildOplinkPortPowerSet()
                .setXid(xidCounter.getAndIncrement())
                .setPort((int) portNum.toLong())
                .setPowerValue((int) power)
                .build());
    }

    /**
     * Gets specified channel attenuation.
     *
     * @param portNum the port number
     * @param och channel signal
     * @return atteuation in 0.01 dB
     */
    private Long getChannelAttenuation(PortNumber portNum, OchSignal och) {
        FlowEntry flowEntry = findFlow(portNum, och);
        if (flowEntry == null) {
            return null;
        }
        List<Instruction> instructions = flowEntry.treatment().allInstructions();
        for (Instruction ins : instructions) {
            if (ins.type() != Instruction.Type.EXTENSION) {
                continue;
            }
            ExtensionTreatment ext = ((Instructions.ExtensionInstructionWrapper) ins).extensionInstruction();
            if (ext.type() == ExtensionTreatmentType.ExtensionTreatmentTypes.OPLINK_ATTENUATION.type()) {
                return (long) ((OplinkAttenuation) ext).getAttenuation();
            }
        }
        return null;
    }

    /**
     * Sets specified channle attenuation.
     *
     * @param portNum the port number
     * @param och channel signal
     * @param power attenuation in 0.01 dB
     */
    private void setChannelAttenuation(PortNumber portNum, OchSignal och, long power) {
        FlowEntry flowEntry = findFlow(portNum, och);
        if (flowEntry == null) {
            log.warn("Target channel power not set");
            return;
        }
        final DriverHandler handler = behaviour.handler();
        for (Instruction ins : flowEntry.treatment().allInstructions()) {
            if (ins.type() != Instruction.Type.EXTENSION) {
                continue;
            }
            ExtensionTreatment ext = ((Instructions.ExtensionInstructionWrapper) ins).extensionInstruction();
            if (ext.type() == ExtensionTreatmentType.ExtensionTreatmentTypes.OPLINK_ATTENUATION.type()) {
                ((OplinkAttenuation) ext).setAttenuation((int) power);
                FlowRuleService service = handler.get(FlowRuleService.class);
                service.applyFlowRules(flowEntry);
                return;
            }
        }
        addAttenuation(flowEntry, power);
    }

    /**
     * Gets specified channle current power.
     *
     * @param portNum the port number
     * @param och channel signal
     * @return power value in 0.01 dBm
     */
    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;
    }

    /**
     * Find matching flow on device.
     *
     * @param portNum the port number
     * @param och channel signal
     * @return flow entry
     */
    private FlowEntry findFlow(PortNumber portNum, OchSignal och) {
        final DriverHandler handler = behaviour.handler();
        FlowRuleService service = handler.get(FlowRuleService.class);
        Iterable<FlowEntry> flowEntries = service.getFlowEntries(handler.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;
    }

    /**
     * Replace flow with new flow containing Oplink attenuation extension instruction. Also resets metrics.
     *
     * @param flowEntry flow entry
     * @param power power value
     */
    private void addAttenuation(FlowEntry flowEntry, long power) {
        FlowRule.Builder flowBuilder = new DefaultFlowRule.Builder()
                .withCookie(flowEntry.id().value())
                .withPriority(flowEntry.priority())
                .forDevice(flowEntry.deviceId())
                .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));
        final DriverHandler handler = behaviour.handler();
        treatmentBuilder.add(Instructions.extension(new OplinkAttenuation((int) power), handler.data().deviceId()));
        flowBuilder.withTreatment(treatmentBuilder.build());

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