/*
 * Copyright 2016 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.oplink;

import org.onlab.util.Frequency;
import org.onosproject.core.CoreService;
import org.onosproject.driver.extensions.OplinkAttenuation;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.Lambda;
import org.onosproject.net.OchSignalType;
import org.onosproject.net.PortNumber;
import org.onosproject.net.driver.HandlerBehaviour;
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.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.Criteria;
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.Instruction;
import org.onosproject.net.flow.instructions.Instructions;

import java.util.List;
import java.util.Set;

/**
 * Oplink optical utilities.
 */
public final class OplinkOpticalUtility {

    // Lambda information supported by device.
    public static final GridType GRID_TYPE = GridType.DWDM;
    public static final int SLOT_GRANULARITY = 4;
    // Channel spacing is 50GHz, 12.5GHz * 4
    public static final ChannelSpacing CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ;
    // Start frequency supported by device.
    public static final Frequency START_CENTER_FREQ = Frequency.ofGHz(191_350);
    // Stop frequency supported by device.
    public static final Frequency STOP_CENTER_FREQ = Frequency.ofGHz(196_100);

    // Power multiply factor, the power accuracy supported by device is 0.01dBm.
    // Transforms the double typed number to long typed power for ONOS.
    public static final int POWER_MULTIPLIER = 100;
    // Attenuation range supported by device, [0, 25dB].
    public static final long MIN_ATTENUATION = 0L;
    public static final long MAX_ATTENUATION = 2500L;

    // Default attenuation value if the attenuation instruction is not found.
    private static final int DEFAULT_ATT = 0;
    // Default flow priority for an extra flow.
    private static final int DEFAULT_PRIORITY = 88;
    // Default application name.
    private static final String DEFAULT_APP = "org.onosproject.drivers.oplink";

    private OplinkOpticalUtility() {
    }

    /**
     * Transforms a flow FlowRule object to an OplinkCrossConnect object.
     * @param behaviour the parent driver handler
     * @param rule FlowRule object
     * @return cross connect object
     */
    public static OplinkCrossConnect fromFlowRule(HandlerBehaviour behaviour, FlowRule rule) {
        // TrafficSelector
        Set<Criterion> criterions = rule.selector().criteria();
        int channel = criterions.stream()
                .filter(c -> c instanceof OchSignalCriterion)
                .map(c -> ((OchSignalCriterion) c).lambda().spacingMultiplier())
                .findAny()
                .orElse(null);
        PortNumber inPort = criterions.stream()
                .filter(c -> c instanceof PortCriterion)
                .map(c -> ((PortCriterion) c).port())
                .findAny()
                .orElse(null);
        // TrafficTreatment
        List<Instruction> instructions = rule.treatment().immediate();
        PortNumber outPort = instructions.stream()
                .filter(c -> c instanceof Instructions.OutputInstruction)
                .map(c -> ((Instructions.OutputInstruction) c).port())
                .findAny()
                .orElse(null);
        int attenuation = instructions.stream()
                .filter(c -> c instanceof Instructions.ExtensionInstructionWrapper)
                .map(c -> ((Instructions.ExtensionInstructionWrapper) c).extensionInstruction())
                .filter(c -> c instanceof OplinkAttenuation)
                .map(c -> ((OplinkAttenuation) c).getAttenuation())
                .findAny()
                .orElse(DEFAULT_ATT);
        return new OplinkCrossConnect(inPort, outPort, channel, attenuation);
    }

    /**
     * Finds the FlowRule from flow rule store by the given cross connect information.
     * Returns an extra flow to remove the flow by ONOS if not found.
     * @param behaviour the parent driver handler
     * @param cfg cross connect information
     * @return the flow rule
     */
    public static FlowRule toFlowRule(HandlerBehaviour behaviour, OplinkCrossConnect cfg) {
        return toFlowRule(behaviour, cfg.getInPort(), cfg.getOutPort(), cfg.getChannel());
    }

    /**
     * Finds the FlowRule from flow rule store by the given ports and channel.
     * Returns an extra flow to remove the flow by ONOS if not found.
     * @param behaviour the parent driver handler
     * @param inPort the input port
     * @param outPort the output port
     * @param channel the specified channel
     * @return the flow rule
     */
    public static FlowRule toFlowRule(HandlerBehaviour behaviour, PortNumber inPort,
                                      PortNumber outPort, Integer channel) {
        FlowRuleService service = behaviour.handler().get(FlowRuleService.class);
        Iterable<FlowEntry> entries = service.getFlowEntries(behaviour.data().deviceId());
        // Try to Find the flow from flow rule store.
        for (FlowEntry entry : entries) {
            Set<Criterion> criterions = entry.selector().criteria();
            // input port
            PortNumber ip = criterions.stream()
                    .filter(c -> c instanceof PortCriterion)
                    .map(c -> ((PortCriterion) c).port())
                    .findAny()
                    .orElse(null);
            // channel
            Integer ch = criterions.stream()
                    .filter(c -> c instanceof OchSignalCriterion)
                    .map(c -> ((OchSignalCriterion) c).lambda().spacingMultiplier())
                    .findAny()
                    .orElse(null);
            // output port
            PortNumber op = entry.treatment().immediate().stream()
                    .filter(c -> c instanceof Instructions.OutputInstruction)
                    .map(c -> ((Instructions.OutputInstruction) c).port())
                    .findAny()
                    .orElse(null);
            if (inPort.equals(ip) && channel.equals(ch) && outPort.equals(op)) {
                // Find the flow.
                return entry;
            }
        }
        // Cannot find the flow from store. So report an extra flow to remove the flow by ONOS.
        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchInPort(inPort)
                .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID))
                .add(Criteria.matchLambda(Lambda.ochSignal(GRID_TYPE, CHANNEL_SPACING, channel, SLOT_GRANULARITY)))
                .build();
        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                .setOutput(outPort)
                .build();
        return DefaultFlowRule.builder()
                .forDevice(behaviour.data().deviceId())
                .withSelector(selector)
                .withTreatment(treatment)
                .withPriority(DEFAULT_PRIORITY)
                .fromApp(behaviour.handler().get(CoreService.class).getAppId(DEFAULT_APP))
                .build();

    }
}
