/*
 * Copyright 2018-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.

 * This work was partially supported by EC H2020 project METRO-HAUL (761727).
 */

package org.onosproject.drivers.odtn.openconfig;

import org.onosproject.net.OchSignal;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.OchSignalCriterion;
import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

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

public class TerminalDeviceFlowRule extends DefaultFlowRule {
    private static final Logger log = LoggerFactory.getLogger(TerminalDeviceFlowRule.class);

    public enum Type {
        CLIENT_INGRESS,
        CLIENT_EGRESS,
        LINE_INGRESS,
        LINE_EGRESS
    }

    //As generated by the OpticalConnectivityIntentCompiler
    private static final int NUM_CRITERIA_LINE_EGRESS_RULE = 3;
    private static final int NUM_INSTRUCTIONS_LINE_EGRESS_RULE = 1;
    private static final int NUM_CRITERIA_LINE_INGRESS_RULE = 1;
    private static final int NUM_INSTRUCTIONS_LINE_INGRESS_RULE = 2;

    //As generated by the OpticalCoircuitIntentCompiler
    private static final int NUM_CRITERIA_CLIENT_RULES = 1;
    private static final int NUM_INSTRUCTIONS_CLIENT_RULES = 1;

    public Type type;

    private PortNumber inPortNumber;
    private PortNumber outPortNumber;
    private OchSignal ochSignal;
    private String connectionName;


    public TerminalDeviceFlowRule(FlowRule rule, List<PortNumber> linePorts) {
        super(rule);

        Set<Criterion> criteria = rule.selector().criteria();
        List<Instruction> instructions = rule.treatment().immediate();

        /*Rules for TerminalDevice are generated in OpticalPathIntentCompiler with two types of intents
        --- OpticalConnectivity intent compilation generates following flow rules
        OPTICAL LINE level at INGRESS node -- criteria: input port; output port, OChSignal;
        OPTICAL LINE level at EGRESS node -- criteria: input port, OChSignal and OCh type; instruction: output port
        --- OpticalCircuit intent compilation generates following flow rules
        CLIENT PORT at INGRESS node -- criteria: input port (OduClt); instruction output port (Och)
        CLIENT PORT at EGRESS node -- criteria: input port (Och); instruction output port (OduClt)*/

        checkArgument((criteria.size() == NUM_CRITERIA_LINE_EGRESS_RULE) ||
                (criteria.size() == NUM_CRITERIA_LINE_INGRESS_RULE) ||
                (criteria.size() == NUM_CRITERIA_CLIENT_RULES),
                "Wrong size of flow rule criteria for TerminalDevice size" + criteria.size());

        checkArgument((instructions.size() == NUM_INSTRUCTIONS_LINE_EGRESS_RULE) ||
                        (instructions.size() == NUM_INSTRUCTIONS_LINE_INGRESS_RULE) ||
                        (instructions.size() == NUM_INSTRUCTIONS_CLIENT_RULES),
                "Wrong size of flow rule instructions for TerminalDevice size " + instructions.size());

        //This is EGRESS rule on the LINE side
        if ((criteria.size() == NUM_CRITERIA_LINE_EGRESS_RULE) &&
                (instructions.size() == NUM_INSTRUCTIONS_LINE_EGRESS_RULE)) {
            log.debug("Building the TerminalDeviceFlowRule for LINE_EGRESS");
            type = Type.LINE_EGRESS;

            criteria.forEach(
                    c -> checkArgument(c instanceof OchSignalCriterion ||
                                    c instanceof OchSignalTypeCriterion ||
                                    c instanceof PortCriterion,
                            "Incompatible flow rule criteria for ADD TerminalDevice: " + criteria
                    )
            );
            instructions.forEach(
                    c -> checkArgument(c instanceof Instructions.OutputInstruction,
                            "Incompatible flow rule instruction for ADD TerminalDevice: " + instructions
                    )
            );

            ochSignal = criteria.stream()
                    .filter(c -> c instanceof OchSignalCriterion)
                    .map(c -> ((OchSignalCriterion) c).lambda())
                    .findAny()
                    .orElse(null);

            inPortNumber = criteria.stream()
                    .filter(c -> c instanceof PortCriterion)
                    .map(c -> ((PortCriterion) c).port())
                    .findAny()
                    .orElse(null);

            outPortNumber = ((Instructions.OutputInstruction) instructions.get(0)).port();

            checkArgument(linePorts.contains(outPortNumber),
                    "Incompatible output port for DROP TerminalDevice");

        }

        //This is INGRESS rule on the LINE side
        if ((criteria.size() == NUM_CRITERIA_LINE_INGRESS_RULE) &&
                (instructions.size() == NUM_INSTRUCTIONS_LINE_INGRESS_RULE)) {
            log.debug("Building the TerminalDeviceFlowRule LINE_INGRESS");
            type = Type.LINE_INGRESS;

            criteria.forEach(
                    c -> checkArgument(
                            c instanceof PortCriterion,
                            "Incompatible flow rule criteria for ADD TerminalDevice: " + criteria
                    )
            );
            instructions.forEach(
                    c -> checkArgument(c.type() == Instruction.Type.L0MODIFICATION ||
                                    c.type() == Instruction.Type.OUTPUT,
                            "Incompatible flow rule instruction for ADD TerminalDevice: " + instructions
                    )
            );

            inPortNumber = criteria.stream()
                    .filter(c -> c instanceof PortCriterion)
                    .map(c -> ((PortCriterion) c).port())
                    .findAny()
                    .orElse(null);

            checkArgument(linePorts.contains(inPortNumber),
                    "Incompatible input port for DROP TerminalDevice");

            ochSignal = instructions.stream()
                    .filter(c -> c.type() == Instruction.Type.L0MODIFICATION)
                    .map(c -> ((L0ModificationInstruction.ModOchSignalInstruction) c).lambda())
                    .findAny()
                    .orElse(null);

            outPortNumber = instructions.stream()
                    .filter(c -> c.type() == Instruction.Type.OUTPUT)
                    .map(c -> ((Instructions.OutputInstruction) c).port())
                    .findAny()
                    .orElse(null);
        }

        //This is INGRESS or EGRESS rule on the CLIENT side
        if ((criteria.size() == NUM_CRITERIA_CLIENT_RULES) &&
                (instructions.size() == NUM_INSTRUCTIONS_CLIENT_RULES)) {

            criteria.forEach(
                    c -> checkArgument(
                            c instanceof PortCriterion,
                            "Incompatible flow rule criteria for ADD TerminalDevice: " + criteria
                    )
            );
            instructions.forEach(
                    c -> checkArgument(c.type() == Instruction.Type.OUTPUT,
                            "Incompatible flow rule instruction for ADD TerminalDevice: " + instructions
                    )
            );

            inPortNumber = criteria.stream()
                    .filter(c -> c instanceof PortCriterion)
                    .map(c -> ((PortCriterion) c).port())
                    .findAny()
                    .orElse(null);

            outPortNumber = instructions.stream()
                    .filter(c -> c.type() == Instruction.Type.OUTPUT)
                    .map(c -> ((Instructions.OutputInstruction) c).port())
                    .findAny()
                    .orElse(null);

            ochSignal = null;

            if (linePorts.contains(outPortNumber)) {
                type = Type.CLIENT_INGRESS;
            } else {
                type = Type.CLIENT_EGRESS;
            }
        }

        if (type == Type.LINE_EGRESS) {
            connectionName = "LineEgress-LinePort-" + inPortNumber.toString()
                    + "-ochSig-" + ochSignal.centralFrequency().toString();
        }
        if (type == Type.LINE_INGRESS) {
            connectionName = "LineIngress-LinePort-" + outPortNumber.toString()
                    + "-ochSig-" + ochSignal.centralFrequency().toString();
        }
        if (type == Type.CLIENT_EGRESS) {
            connectionName = "ClientEgress-LinePort-" + inPortNumber.toString()
                    + "-ClientPort-" + outPortNumber.toString();
        }
        if (type == Type.CLIENT_INGRESS) {
            connectionName = "ClientIngress-ClientPort-" + inPortNumber.toString()
                    + "-LinePort-" + outPortNumber.toString();
        }

        log.info("TerminalFlowRule built with name {}", connectionName);
    }

    public PortNumber inPort() {
        return inPortNumber;
    }

    public PortNumber outPort() {
        return outPortNumber;
    }

    public OchSignal ochSignal() {
        return ochSignal;
    }

    public String connectionName() {
        return connectionName;
    }
}

