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

import com.google.common.collect.Lists;
import org.apache.commons.lang3.tuple.Pair;
import org.onosproject.driver.optical.flowrule.CrossConnectCache;
import org.onosproject.driver.optical.flowrule.CrossConnectFlowRule;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OchSignalType;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.DefaultFlowEntry;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowId;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleProgrammable;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.PDU;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.UnsignedInteger32;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.util.TreeEvent;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkArgument;

// TODO: need to convert between OChSignal and XC channel number
public class LumentumSdnRoadmFlowRuleProgrammable extends AbstractHandlerBehaviour implements FlowRuleProgrammable {

    private static final Logger log =
            LoggerFactory.getLogger(LumentumSdnRoadmFlowRuleProgrammable.class);

    // Default values
    private static final int DEFAULT_TARGET_GAIN_PREAMP = 150;
    private static final int DEFAULT_TARGET_GAIN_BOOSTER = 200;
    private static final int DISABLE_CHANNEL_TARGET_POWER = -650;
    private static final int DEFAULT_CHANNEL_TARGET_POWER = -30;
    private static final int DISABLE_CHANNEL_ABSOLUTE_ATTENUATION = 160;
    private static final int DEFAULT_CHANNEL_ABSOLUTE_ATTENUATION = 50;
    private static final int DISABLE_CHANNEL_ADD_DROP_PORT_INDEX = 1;
    private static final int OUT_OF_SERVICE = 1;
    private static final int IN_SERVICE = 2;
    private static final int OPEN_LOOP = 1;
    private static final int CLOSED_LOOP = 2;
    // First 20 ports are add/mux ports, next 20 are drop/demux
    private static final int DROP_PORT_OFFSET = 20;

    // OIDs
    private static final String CTRL_AMP_MODULE_SERVICE_STATE_PREAMP = ".1.3.6.1.4.1.46184.1.4.4.1.2.1";
    private static final String CTRL_AMP_MODULE_SERVICE_STATE_BOOSTER = ".1.3.6.1.4.1.46184.1.4.4.1.2.2";
    private static final String CTRL_AMP_MODULE_TARGET_GAIN_PREAMP = ".1.3.6.1.4.1.46184.1.4.4.1.8.1";
    private static final String CTRL_AMP_MODULE_TARGET_GAIN_BOOSTER = ".1.3.6.1.4.1.46184.1.4.4.1.8.2";
    private static final String CTRL_CHANNEL_STATE = ".1.3.6.1.4.1.46184.1.4.2.1.3.";
    private static final String CTRL_CHANNEL_MODE = ".1.3.6.1.4.1.46184.1.4.2.1.4.";
    private static final String CTRL_CHANNEL_TARGET_POWER = ".1.3.6.1.4.1.46184.1.4.2.1.6.";
    private static final String CTRL_CHANNEL_ADD_DROP_PORT_INDEX = ".1.3.6.1.4.1.46184.1.4.2.1.13.";
    private static final String CTRL_CHANNEL_ABSOLUTE_ATTENUATION = ".1.3.6.1.4.1.46184.1.4.2.1.5.";

    private LumentumSnmpDevice snmp;

    @Override
    public Collection<FlowEntry> getFlowEntries() {
        try {
            snmp = new LumentumSnmpDevice(handler().data().deviceId());
        } catch (IOException e) {
            log.error("Failed to connect to device: ", e);
            return Collections.emptyList();
        }

        // Line in is last but one port, line out is last
        DeviceService deviceService = this.handler().get(DeviceService.class);
        List<Port> ports = deviceService.getPorts(data().deviceId());
        if (ports.size() < 2) {
            return Collections.emptyList();
        }
        PortNumber lineIn = ports.get(ports.size() - 2).number();
        PortNumber lineOut = ports.get(ports.size() - 1).number();

        Collection<FlowEntry> entries = Lists.newLinkedList();

        // Add rules
        OID addOid = new OID(CTRL_CHANNEL_STATE + "1");
        entries.addAll(
                fetchRules(addOid, true, lineOut).stream()
                        .map(fr -> new DefaultFlowEntry(fr, FlowEntry.FlowEntryState.ADDED, 0, 0, 0))
                        .collect(Collectors.toList())
        );

        // Drop rules
        OID dropOid = new OID(CTRL_CHANNEL_STATE + "2");
        entries.addAll(
                fetchRules(dropOid, false, lineIn).stream()
                        .map(fr -> new DefaultFlowEntry(fr, FlowEntry.FlowEntryState.ADDED, 0, 0, 0))
                        .collect(Collectors.toList())
        );

        return entries;
    }

    @Override
    public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
        try {
            snmp = new LumentumSnmpDevice(data().deviceId());
        } catch (IOException e) {
            log.error("Failed to connect to device: ", e);
        }

        // Line ports
        DeviceService deviceService = this.handler().get(DeviceService.class);
        List<Port> ports = deviceService.getPorts(data().deviceId());
        List<PortNumber> linePorts = ports.subList(ports.size() - 2, ports.size()).stream()
                .map(p -> p.number())
                .collect(Collectors.toList());

        // Apply the valid rules on the device
        Collection<FlowRule> added = rules.stream()
                .map(r -> new CrossConnectFlowRule(r, linePorts))
                .filter(xc -> installCrossConnect(xc))
                .collect(Collectors.toList());

        // Cache the cookie/priority
        CrossConnectCache cache = this.handler().get(CrossConnectCache.class);
        added.forEach(xc -> cache.set(
                Objects.hash(data().deviceId(), xc.selector(), xc.treatment()),
                xc.id(),
                xc.priority()));

        return added;
    }

    @Override
    public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
        try {
            snmp = new LumentumSnmpDevice(data().deviceId());
        } catch (IOException e) {
            log.error("Failed to connect to device: ", e);
        }

        // Line ports
        DeviceService deviceService = this.handler().get(DeviceService.class);
        List<Port> ports = deviceService.getPorts(data().deviceId());
        List<PortNumber> linePorts = ports.subList(ports.size() - 2, ports.size()).stream()
                .map(p -> p.number())
                .collect(Collectors.toList());

        // Apply the valid rules on the device
        Collection<FlowRule> removed = rules.stream()
                .map(r -> new CrossConnectFlowRule(r, linePorts))
                .filter(xc -> removeCrossConnect(xc))
                .collect(Collectors.toList());

        // Remove flow rule from cache
        CrossConnectCache cache = this.handler().get(CrossConnectCache.class);
        removed.forEach(xc -> cache.remove(
                Objects.hash(data().deviceId(), xc.selector(), xc.treatment())));

        return removed;
    }

    // Installs cross connect on device
    private boolean installCrossConnect(CrossConnectFlowRule xc) {

        int channel = toChannel(xc.ochSignal());
        long addDrop = xc.addDrop().toLong();
        if (!xc.isAddRule()) {
            addDrop -= DROP_PORT_OFFSET;
        }

        // Create the PDU object
        PDU pdu = new PDU();
        pdu.setType(PDU.SET);

        // Enable preamp & booster
        List<OID> oids = Arrays.asList(new OID(CTRL_AMP_MODULE_SERVICE_STATE_PREAMP),
                new OID(CTRL_AMP_MODULE_SERVICE_STATE_BOOSTER));
        oids.forEach(
                oid -> pdu.add(new VariableBinding(oid, new Integer32(IN_SERVICE)))
        );

        // Set target gain on preamp & booster
        OID ctrlAmpModuleTargetGainPreamp = new OID(CTRL_AMP_MODULE_TARGET_GAIN_PREAMP);
        pdu.add(new VariableBinding(ctrlAmpModuleTargetGainPreamp, new Integer32(DEFAULT_TARGET_GAIN_PREAMP)));
        OID ctrlAmpModuleTargetGainBooster = new OID(CTRL_AMP_MODULE_TARGET_GAIN_BOOSTER);
        pdu.add(new VariableBinding(ctrlAmpModuleTargetGainBooster, new Integer32(DEFAULT_TARGET_GAIN_BOOSTER)));

        // Make cross connect
        OID ctrlChannelAddDropPortIndex = new OID(CTRL_CHANNEL_ADD_DROP_PORT_INDEX +
                (xc.isAddRule() ? "1." : "2.") + channel);
        pdu.add(new VariableBinding(ctrlChannelAddDropPortIndex, new UnsignedInteger32(addDrop)));

        // Add rules use closed loop, drop rules open loop
        // Add rules are set to target power, drop rules are attenuated
        if (xc.isAddRule()) {
            OID ctrlChannelMode = new OID(CTRL_CHANNEL_MODE + "1." + channel);
            pdu.add(new VariableBinding(ctrlChannelMode, new Integer32(CLOSED_LOOP)));

            OID ctrlChannelTargetPower = new OID(CTRL_CHANNEL_TARGET_POWER + "1." + channel);
            pdu.add(new VariableBinding(ctrlChannelTargetPower, new Integer32(DEFAULT_CHANNEL_TARGET_POWER)));
        } else {
            OID ctrlChannelMode = new OID(CTRL_CHANNEL_MODE + "2." + channel);
            pdu.add(new VariableBinding(ctrlChannelMode, new Integer32(OPEN_LOOP)));

            OID ctrlChannelAbsoluteAttenuation = new OID(CTRL_CHANNEL_ABSOLUTE_ATTENUATION + "2." + channel);
            pdu.add(new VariableBinding(
                    ctrlChannelAbsoluteAttenuation, new UnsignedInteger32(DEFAULT_CHANNEL_ABSOLUTE_ATTENUATION)));
        }

        // Final step is to enable the channel
        OID ctrlChannelState = new OID(CTRL_CHANNEL_STATE + (xc.isAddRule() ? "1." : "2.") + channel);
        pdu.add(new VariableBinding(ctrlChannelState, new Integer32(IN_SERVICE)));

        try {
            ResponseEvent response = snmp.set(pdu);

             // TODO: parse response
        } catch (IOException e) {
            log.error("Failed to create cross connect, unable to connect to device: ", e);
        }

        return true;
    }

    // Removes cross connect on device
    private boolean removeCrossConnect(CrossConnectFlowRule xc) {

        int channel = toChannel(xc.ochSignal());

        // Create the PDU object
        PDU pdu = new PDU();
        pdu.setType(PDU.SET);

        // Disable the channel
        OID ctrlChannelState = new OID(CTRL_CHANNEL_STATE + (xc.isAddRule() ? "1." : "2.") + channel);
        pdu.add(new VariableBinding(ctrlChannelState, new Integer32(OUT_OF_SERVICE)));

        // Put cross connect back into default port 1
        OID ctrlChannelAddDropPortIndex = new OID(CTRL_CHANNEL_ADD_DROP_PORT_INDEX +
                (xc.isAddRule() ? "1." : "2.") + channel);
        pdu.add(new VariableBinding(ctrlChannelAddDropPortIndex,
                new UnsignedInteger32(DISABLE_CHANNEL_ADD_DROP_PORT_INDEX)));

        // Put port/channel back to open loop
        OID ctrlChannelMode = new OID(CTRL_CHANNEL_MODE + (xc.isAddRule() ? "1." : "2.") + channel);
        pdu.add(new VariableBinding(ctrlChannelMode, new Integer32(OPEN_LOOP)));

        // Add rules are set to target power, drop rules are attenuated
        if (xc.isAddRule()) {
            OID ctrlChannelTargetPower = new OID(CTRL_CHANNEL_TARGET_POWER + "1." + channel);
            pdu.add(new VariableBinding(ctrlChannelTargetPower, new Integer32(DISABLE_CHANNEL_TARGET_POWER)));
        } else {
            OID ctrlChannelAbsoluteAttenuation = new OID(CTRL_CHANNEL_ABSOLUTE_ATTENUATION + "2." + channel);
            pdu.add(new VariableBinding(
                    ctrlChannelAbsoluteAttenuation, new UnsignedInteger32(DISABLE_CHANNEL_ABSOLUTE_ATTENUATION)));
        }

        try {
            ResponseEvent response = snmp.set(pdu);

            // TODO: parse response
        } catch (IOException e) {
            log.error("Failed to remove cross connect, unable to connect to device: ", e);
            return false;
        }

        return true;
    }

    /**
     * Convert OCh signal to Lumentum channel ID.
     *
     * @param ochSignal OCh signal
     * @return Lumentum channel ID
     */
    public static int toChannel(OchSignal ochSignal) {
        // FIXME: move to cross connect validation
        checkArgument(ochSignal.channelSpacing() == ChannelSpacing.CHL_50GHZ);
        checkArgument(LumentumSnmpDevice.START_CENTER_FREQ.compareTo(ochSignal.centralFrequency()) <= 0);
        checkArgument(LumentumSnmpDevice.END_CENTER_FREQ.compareTo(ochSignal.centralFrequency()) >= 0);

        return ochSignal.spacingMultiplier() + LumentumSnmpDevice.MULTIPLIER_SHIFT;
    }

    /**
     * Convert Lumentum channel ID to OCh signal.
     *
     * @param channel Lumentum channel ID
     * @return OCh signal
     */
    public static OchSignal toOchSignal(int channel) {
        checkArgument(1 <= channel);
        checkArgument(channel <= 96);

        return new OchSignal(GridType.DWDM, ChannelSpacing.CHL_50GHZ,
                channel - LumentumSnmpDevice.MULTIPLIER_SHIFT, 4);
    }

    // Returns the currently configured add/drop port for the given channel.
    private PortNumber getAddDropPort(int channel, boolean isAddPort) {
        OID oid = new OID(CTRL_CHANNEL_ADD_DROP_PORT_INDEX + (isAddPort ? "1" : "2"));

        for (TreeEvent event : snmp.get(oid)) {
            if (event == null) {
                return null;
            }

            VariableBinding[] varBindings = event.getVariableBindings();

            for (VariableBinding varBinding : varBindings) {
                if (varBinding.getOid().last() == channel) {
                    int port = varBinding.getVariable().toInt();
                    if (!isAddPort) {
                        port += DROP_PORT_OFFSET;
                    }
                    return PortNumber.portNumber(port);

                }
            }

        }

        return null;
    }

    // Returns the currently installed flow entries on the device.
    private List<FlowRule> fetchRules(OID oid, boolean isAdd, PortNumber linePort) {
        List<FlowRule> rules = new LinkedList<>();

        for (TreeEvent event : snmp.get(oid)) {
            if (event == null) {
                continue;
            }

            VariableBinding[] varBindings = event.getVariableBindings();
            for (VariableBinding varBinding : varBindings) {
                CrossConnectCache cache = this.handler().get(CrossConnectCache.class);

                if (varBinding.getVariable().toInt() == IN_SERVICE) {
                    int channel = varBinding.getOid().removeLast();

                    PortNumber addDropPort = getAddDropPort(channel, isAdd);
                    if (addDropPort == null) {
                        continue;
                    }

                    TrafficSelector selector = DefaultTrafficSelector.builder()
                            .matchInPort(isAdd ? addDropPort : linePort)
                            .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID))
                            .add(Criteria.matchLambda(toOchSignal(channel)))
                            .build();
                    TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                            .setOutput(isAdd ? linePort : addDropPort)
                            .build();

                    // Lookup flow ID and priority
                    int hash = Objects.hash(data().deviceId(), selector, treatment);
                    Pair<FlowId, Integer> lookup = cache.get(hash);
                    if (lookup == null) {
                        continue;
                    }

                    FlowRule fr = DefaultFlowRule.builder()
                            .forDevice(data().deviceId())
                            .makePermanent()
                            .withSelector(selector)
                            .withTreatment(treatment)
                            .withPriority(lookup.getRight())
                            .withCookie(lookup.getLeft().value())
                            .build();
                    rules.add(fr);
                }
            }
        }

        return rules;
    }
}
