/*
 * Copyright 2015 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.net.flowobjective.impl.composition;

import org.onlab.packet.IpPrefix;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
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.LambdaCriterion;
import org.onosproject.net.flow.criteria.OchSignalCriterion;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.criteria.VlanPcpCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
import org.onosproject.net.flow.criteria.OduSignalIdCriterion;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
import org.onosproject.net.flow.instructions.L1ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

/**
 * Provide util functions for FlowObjectiveComposition.
 */
public final class FlowObjectiveCompositionUtil {

    private FlowObjectiveCompositionUtil() {}

    // only work with VERSATILE
    public static ForwardingObjective composeParallel(ForwardingObjective fo1, ForwardingObjective fo2) {

        TrafficSelector trafficSelector = intersectTrafficSelector(fo1.selector(), fo2.selector());
        if (trafficSelector == null) {
            return null;
        }

        TrafficTreatment trafficTreatment = unionTrafficTreatment(fo1.treatment(), fo2.treatment());

        return DefaultForwardingObjective.builder()
                .fromApp(fo1.appId())
                .makePermanent()
                .withFlag(ForwardingObjective.Flag.VERSATILE)
                .withPriority(fo1.priority() + fo2.priority())
                .withSelector(trafficSelector)
                .withTreatment(trafficTreatment)
                .add();
    }

    public static ForwardingObjective composeSequential(ForwardingObjective fo1,
                                                        ForwardingObjective fo2,
                                                        int priorityMultiplier) {

        TrafficSelector revertTrafficSelector = revertTreatmentSelector(fo1.treatment(), fo2.selector());
        if (revertTrafficSelector == null) {
            return null;
        }

        TrafficSelector trafficSelector = intersectTrafficSelector(fo1.selector(), revertTrafficSelector);
        if (trafficSelector == null) {
            return null;
        }

        TrafficTreatment trafficTreatment = unionTrafficTreatment(fo1.treatment(), fo2.treatment());

        return DefaultForwardingObjective.builder()
                .fromApp(fo1.appId())
                .makePermanent()
                .withFlag(ForwardingObjective.Flag.VERSATILE)
                .withPriority(fo1.priority() * priorityMultiplier + fo2.priority())
                .withSelector(trafficSelector)
                .withTreatment(trafficTreatment)
                .add();
    }

    public static ForwardingObjective composeOverride(ForwardingObjective fo, int priorityAddend) {
        return DefaultForwardingObjective.builder()
                .fromApp(fo.appId())
                .makePermanent()
                .withFlag(fo.flag())
                .withPriority(fo.priority() + priorityAddend)
                .withSelector(fo.selector())
                .withTreatment(fo.treatment())
                .add();
    }

    public static TrafficSelector intersectTrafficSelector(TrafficSelector ts1, TrafficSelector ts2) {

        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();

        Set<Criterion.Type> ts1IntersectTs2 = getTypeSet(ts1);
        ts1IntersectTs2.retainAll(getTypeSet(ts2));
        for (Criterion.Type type : ts1IntersectTs2) {
            Criterion criterion = intersectCriterion(ts1.getCriterion(type), ts2.getCriterion(type));
            if (criterion == null) {
                return null;
            } else {
                selectorBuilder.add(criterion);
            }
        }

        Set<Criterion.Type> ts1MinusTs2 = getTypeSet(ts1);
        ts1MinusTs2.removeAll(getTypeSet(ts2));
        for (Criterion.Type type : ts1MinusTs2) {
            selectorBuilder.add(ts1.getCriterion(type));
        }

        Set<Criterion.Type> ts2MinusTs1 = getTypeSet(ts2);
        ts2MinusTs1.removeAll(getTypeSet(ts1));
        for (Criterion.Type type : ts2MinusTs1) {
            selectorBuilder.add(ts2.getCriterion(type));
        }

        return selectorBuilder.build();
    }

    public static TrafficTreatment unionTrafficTreatment(TrafficTreatment tt1, TrafficTreatment tt2) {

        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();

        for (Instruction instruction : tt1.allInstructions()) {
            treatmentBuilder.add(instruction);
        }

        for (Instruction instruction : tt2.allInstructions()) {
            treatmentBuilder.add(instruction);
        }

        return treatmentBuilder.build();
    }

    //CHECKSTYLE:OFF
    public static TrafficSelector revertTreatmentSelector(TrafficTreatment trafficTreatment,
                                                          TrafficSelector trafficSelector) {

        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();

        Map<Criterion.Type, Criterion> criterionMap = new HashMap<>();
        for (Criterion criterion : trafficSelector.criteria()) {
            criterionMap.put(criterion.type(), criterion);
        }

        for (Instruction instruction : trafficTreatment.allInstructions()) {
            switch (instruction.type()) {
                case DROP:
                    return null;
                case OUTPUT:
                    break;
                case GROUP:
                    break;
                case L0MODIFICATION: {
                    L0ModificationInstruction l0 = (L0ModificationInstruction) instruction;
                    switch (l0.subtype()) {
                        case LAMBDA:
                            if (criterionMap.containsKey(Criterion.Type.OCH_SIGID)) {
                                if (((LambdaCriterion) criterionMap.get((Criterion.Type.OCH_SIGID))).lambda()
                                        == ((L0ModificationInstruction.ModLambdaInstruction) l0).lambda()) {
                                    criterionMap.remove(Criterion.Type.OCH_SIGID);
                                } else {
                                    return null;
                                }
                            } else {
                                break;
                            }
                        case OCH:
                            if (criterionMap.containsKey(Criterion.Type.OCH_SIGID)) {
                                if (((OchSignalCriterion) criterionMap.get((Criterion.Type.OCH_SIGID))).lambda()
                                        .equals(((L0ModificationInstruction.ModOchSignalInstruction) l0).lambda())) {
                                    criterionMap.remove(Criterion.Type.OCH_SIGID);
                                } else {
                                    return null;
                                }
                            }
                        default:
                            break;
                    }
                    break;
                }
                case L1MODIFICATION: {
                    L1ModificationInstruction l1 = (L1ModificationInstruction) instruction;
                    switch (l1.subtype()) {
                        case ODU_SIGID:
                            if (criterionMap.containsKey(Criterion.Type.ODU_SIGID)) {
                                if (((OduSignalIdCriterion) criterionMap.get((Criterion.Type.ODU_SIGID))).oduSignalId()
                                        .equals(((L1ModificationInstruction.ModOduSignalIdInstruction) l1)
                                                .oduSignalId())) {
                                    criterionMap.remove(Criterion.Type.ODU_SIGID);
                                } else {
                                    return null;
                                }
                            } 
                        default:
                            break;
                    }
                    break;
                }
                case L2MODIFICATION: {
                    L2ModificationInstruction l2 = (L2ModificationInstruction) instruction;
                    switch (l2.subtype()) {
                        case ETH_SRC:
                            if (criterionMap.containsKey(Criterion.Type.ETH_SRC)) {
                                if (((EthCriterion) criterionMap.get((Criterion.Type.ETH_SRC))).mac()
                                        .equals(((L2ModificationInstruction.ModEtherInstruction) l2).mac())) {
                                    criterionMap.remove(Criterion.Type.ETH_SRC);
                                } else {
                                    return null;
                                }
                            } else {
                                break;
                            }
                        case ETH_DST:
                            if (criterionMap.containsKey(Criterion.Type.ETH_DST)) {
                                if (((EthCriterion) criterionMap.get((Criterion.Type.ETH_DST))).mac()
                                        .equals(((L2ModificationInstruction.ModEtherInstruction) l2).mac())) {
                                    criterionMap.remove(Criterion.Type.ETH_DST);
                                } else {
                                    return null;
                                }
                            } else {
                                break;
                            }
                        case VLAN_ID:
                            if (criterionMap.containsKey(Criterion.Type.VLAN_VID)) {
                                if (((VlanIdCriterion) criterionMap.get((Criterion.Type.VLAN_VID))).vlanId()
                                        .equals(((L2ModificationInstruction.ModVlanIdInstruction) l2).vlanId())) {
                                    criterionMap.remove(Criterion.Type.VLAN_VID);
                                } else {
                                    return null;
                                }
                            } else {
                                break;
                            }
                        case VLAN_PCP:
                            if (criterionMap.containsKey(Criterion.Type.VLAN_PCP)) {
                                if (((VlanPcpCriterion) criterionMap.get((Criterion.Type.VLAN_PCP))).priority()
                                        == ((L2ModificationInstruction.ModVlanPcpInstruction) l2).vlanPcp()) {
                                    criterionMap.remove(Criterion.Type.VLAN_PCP);
                                } else {
                                    return null;
                                }
                            } else {
                                break;
                            }
                        case MPLS_LABEL:
                            if (criterionMap.containsKey(Criterion.Type.MPLS_LABEL)) {
                                if (((MplsCriterion) criterionMap.get((Criterion.Type.MPLS_LABEL))).label()
                                        .equals(((L2ModificationInstruction.ModMplsLabelInstruction) l2).mplsLabel())) {
                                    criterionMap.remove(Criterion.Type.ETH_DST);
                                } else {
                                    return null;
                                }
                            } else {
                                break;
                            }
                        default:
                            break;
                    }
                    break;
                }
                case TABLE:
                    break;
                case L3MODIFICATION: {
                    L3ModificationInstruction l3 = (L3ModificationInstruction) instruction;
                    switch (l3.subtype()) {
                        case IPV4_SRC:
                            if (criterionMap.containsKey(Criterion.Type.IPV4_SRC)) {
                                if (((IPCriterion) criterionMap.get(Criterion.Type.IPV4_SRC)).ip()
                                        .contains(((L3ModificationInstruction.ModIPInstruction) l3).ip())) {
                                    criterionMap.remove(Criterion.Type.IPV4_SRC);
                                } else {
                                    return null;
                                }
                            } else {
                                break;
                            }
                        case IPV4_DST:
                            if (criterionMap.containsKey(Criterion.Type.IPV4_DST)) {
                                if (((IPCriterion) criterionMap.get(Criterion.Type.IPV4_DST)).ip()
                                        .contains(((L3ModificationInstruction.ModIPInstruction) l3).ip())) {
                                    criterionMap.remove(Criterion.Type.IPV4_DST);
                                } else {
                                    return null;
                                }
                            } else {
                                break;
                            }
                        case IPV6_SRC:
                            if (criterionMap.containsKey(Criterion.Type.IPV6_SRC)) {
                                if (((IPCriterion) criterionMap.get(Criterion.Type.IPV6_SRC)).ip()
                                        .contains(((L3ModificationInstruction.ModIPInstruction) l3).ip())) {
                                    criterionMap.remove(Criterion.Type.IPV6_SRC);
                                } else {
                                    return null;
                                }
                            } else {
                                break;
                            }
                        case IPV6_DST:
                            if (criterionMap.containsKey(Criterion.Type.IPV6_DST)) {
                                if (((IPCriterion) criterionMap.get(Criterion.Type.IPV6_DST)).ip()
                                        .contains(((L3ModificationInstruction.ModIPInstruction) l3).ip())) {
                                    criterionMap.remove(Criterion.Type.IPV6_DST);
                                } else {
                                    return null;
                                }
                            } else {
                                break;
                            }
                        case IPV6_FLABEL:
                            if (criterionMap.containsKey(Criterion.Type.IPV6_FLABEL)) {
                                if (((IPv6FlowLabelCriterion) criterionMap.get(Criterion.Type.IPV6_FLABEL)).flowLabel()
                                        == (((L3ModificationInstruction.ModIPv6FlowLabelInstruction) l3).flowLabel())) {
                                    criterionMap.remove(Criterion.Type.IPV4_SRC);
                                } else {
                                    return null;
                                }
                            } else {
                                break;
                            }
                        default:
                            break;
                    }
                    break;
                }
                case METADATA:
                    break;
                default:
                    break;
            }
        }

        for (Criterion criterion : criterionMap.values()) {
            selectorBuilder.add(criterion);
        }

        return selectorBuilder.build();
    }
   //CHECKSTYLE:ON

    public static Set<Criterion.Type> getTypeSet(TrafficSelector trafficSelector) {
        Set<Criterion.Type> typeSet = new HashSet<>();
        for (Criterion criterion : trafficSelector.criteria()) {
            typeSet.add(criterion.type());
        }
        return typeSet;
    }

    public static Criterion intersectCriterion(Criterion c1, Criterion c2) {
        switch (c1.type()) {
            case IPV4_SRC: {
                IpPrefix ipPrefix = intersectIpPrefix(((IPCriterion) c1).ip(), ((IPCriterion) c2).ip());
                if (ipPrefix == null) {
                    return null;
                } else {
                    return Criteria.matchIPSrc(ipPrefix);
                }
            }
            case IPV4_DST: {
                IpPrefix ipPrefix = intersectIpPrefix(((IPCriterion) c1).ip(), ((IPCriterion) c2).ip());
                if (ipPrefix == null) {
                    return null;
                } else {
                    return Criteria.matchIPDst(ipPrefix);
                }
            }
            case IPV6_SRC: {
                IpPrefix ipPrefix = intersectIpPrefix(((IPCriterion) c1).ip(), ((IPCriterion) c2).ip());
                if (ipPrefix == null) {
                    return null;
                } else {
                    return Criteria.matchIPv6Src(ipPrefix);
                }
            }
            case IPV6_DST: {
                IpPrefix ipPrefix = intersectIpPrefix(((IPCriterion) c1).ip(), ((IPCriterion) c2).ip());
                if (ipPrefix == null) {
                    return null;
                } else {
                    return Criteria.matchIPv6Dst(ipPrefix);
                }
            }
            default:
                if (!c1.equals(c2)) {
                    return null;
                } else {
                    return c1;
                }
        }
    }

    public static IpPrefix intersectIpPrefix(IpPrefix ip1, IpPrefix ip2) {
        if (ip1.contains(ip2)) {
            return ip1;
        } else if (ip2.contains(ip1)) {
            return ip2;
        } else {
            return null;
        }
    }

    public static FlowObjectiveCompositionTree parsePolicyString(String policy) {
        List<FlowObjectiveCompositionTree> postfix = transformToPostfixForm(policy);
        return buildPolicyTree(postfix);
    }

    private static List<FlowObjectiveCompositionTree> transformToPostfixForm(String policy) {
        Stack<Character> stack = new Stack<>();
        List<FlowObjectiveCompositionTree> postfix = new ArrayList<>();

        for (int i = 0; i < policy.length(); i++) {
            Character ch = policy.charAt(i);
            if (Character.isDigit(ch)) {

                int applicationId = ch - '0';
                while (i + 1 < policy.length() && Character.isDigit(policy.charAt(i + 1))) {
                    i++;
                    applicationId = applicationId * 10 + policy.charAt(i) - '0';
                }

                postfix.add(new FlowObjectiveCompositionTree((short) applicationId));
            } else if (ch == '(') {
                stack.push(ch);
            } else if (ch == ')') {
                while (stack.peek() != '(') {
                    postfix.add(new FlowObjectiveCompositionTree(stack.pop()));
                }
                stack.pop();
            } else {
                while (!stack.isEmpty() && compareOperatorPriority(stack.peek(), ch)) {
                    postfix.add(new FlowObjectiveCompositionTree(stack.pop()));
                }
                stack.push(ch);
            }
        }
        while (!stack.isEmpty()) {
            postfix.add(new FlowObjectiveCompositionTree(stack.pop()));
        }

        return postfix;
    }

    private static boolean compareOperatorPriority(char peek, char cur) {
        if (peek == '/' && (cur == '+' || cur == '>' || cur == '/')) {
            return true;
        } else if (peek == '>' && (cur == '+' || cur == '>')) {
            return true;
        } else if (peek == '+' && cur == '+') {
            return true;
        }
        return false;
    }

    private static FlowObjectiveCompositionTree buildPolicyTree(List<FlowObjectiveCompositionTree> postfix) {
        Stack<FlowObjectiveCompositionTree> stack = new Stack<>();
        for (FlowObjectiveCompositionTree node : postfix) {
            if (node.operator == FlowObjectiveCompositionManager.PolicyOperator.Application) {
                stack.push(node);
            } else {
                node.rightChild = stack.pop();
                node.leftChild = stack.pop();
                stack.push(node);
            }
        }
        return stack.pop();
    }

    public static Collection<ForwardingObjective> minusForwardingObjectives(Collection<ForwardingObjective> fo1,
                                                                            Collection<ForwardingObjective> fo2) {
        Map<Integer, ForwardingObjective> map = new HashMap<>();
        for (ForwardingObjective fo : fo1) {
            map.put(fo.id(), fo);
        }
        for (ForwardingObjective fo : fo2) {
            map.remove(fo.id());
        }
        return map.values();
    }


}
