/*
 * 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.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 OUTPUT:
                    break;
                case GROUP:
                    break;
                case L0MODIFICATION: {
                    L0ModificationInstruction l0 = (L0ModificationInstruction) instruction;
                    switch (l0.subtype()) {
                        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).label())) {
                                    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();
    }


}
