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

import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.SetMultimap;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.util.Identifier;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompilationException;
import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.LinkCollectionIntent;
import org.onosproject.net.intent.constraint.EncapsulationConstraint;
import org.onosproject.net.resource.ResourceService;
import org.onosproject.net.resource.impl.LabelAllocator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import static org.onosproject.net.flow.instructions.Instruction.Type.NOACTION;

/**
 * Compiler to produce flow rules from link collections.
 */
@Component(immediate = true)
public class LinkCollectionIntentCompiler
        extends LinkCollectionCompiler<FlowRule>
        implements IntentCompiler<LinkCollectionIntent> {

    private static final String UNKNOWN_INSTRUCTION = "Unknown instruction type";
    private static final String UNSUPPORTED_INSTRUCTION = "Unsupported %s instruction";

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


    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected IntentConfigurableRegistrator registrator;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ResourceService resourceService;

    private ApplicationId appId;

    @Activate
    public void activate() {
        appId = coreService.registerApplication("org.onosproject.net.intent");
        registrator.registerCompiler(LinkCollectionIntent.class, this, false);
        if (labelAllocator == null) {
            labelAllocator = new LabelAllocator(resourceService);
        }
    }

    @Deactivate
    public void deactivate() {
        registrator.unregisterCompiler(LinkCollectionIntent.class, false);
    }

    @Override
    public List<Intent> compile(LinkCollectionIntent intent, List<Intent> installable) {

        SetMultimap<DeviceId, PortNumber> inputPorts = HashMultimap.create();
        SetMultimap<DeviceId, PortNumber> outputPorts = HashMultimap.create();
        Map<ConnectPoint, Identifier<?>> labels = ImmutableMap.of();

        Optional<EncapsulationConstraint> encapConstraint = this.getIntentEncapConstraint(intent);

        computePorts(intent, inputPorts, outputPorts);

        if (encapConstraint.isPresent()) {
            labels = labelAllocator.assignLabelToPorts(intent.links(),
                                                       intent.id(),
                                                       encapConstraint.get().encapType());
        }

        List<FlowRule> rules = new ArrayList<>();
        for (DeviceId deviceId: outputPorts.keySet()) {
            rules.addAll(createRules(
                    intent,
                    deviceId,
                    inputPorts.get(deviceId),
                    outputPorts.get(deviceId),
                    labels)
            );
        }
        return Collections.singletonList(new FlowRuleIntent(appId, intent.key(), rules, intent.resources()));
    }

    @Override
    protected List<FlowRule> createRules(LinkCollectionIntent intent,
                                         DeviceId deviceId,
                                         Set<PortNumber> inPorts,
                                         Set<PortNumber> outPorts,
                                         Map<ConnectPoint, Identifier<?>> labels) {

        List<FlowRule> rules = new ArrayList<>(inPorts.size());
        /*
         * Looking for the encapsulation constraint
         */
        Optional<EncapsulationConstraint> encapConstraint = this.getIntentEncapConstraint(intent);

        inPorts.forEach(inport -> {

                ForwardingInstructions instructions = this.createForwardingInstruction(
                        encapConstraint,
                        intent,
                        inport,
                        outPorts,
                        deviceId,
                        labels
                );

                if (optimize) {
                    TrafficTreatment compactedTreatment = compactActions(instructions.treatment());
                    instructions = new ForwardingInstructions(compactedTreatment, instructions.selector());
                }

                FlowRule rule = DefaultFlowRule.builder()
                        .forDevice(deviceId)
                        .withSelector(instructions.selector())
                        .withTreatment(instructions.treatment())
                        .withPriority(intent.priority())
                        .fromApp(appId)
                        .makePermanent()
                        .build();
                rules.add(rule);
            }
        );

        return rules;
    }

    /**
     * This method tries to optimize the chain of actions.
     *
     * @param oldTreatment the list of instructions to optimize
     * @return the optimized set of actions
     */
    private TrafficTreatment compactActions(TrafficTreatment oldTreatment) {

        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
        Instruction instruction;
        Instruction newInstruction;

        for (int index = 0; index < oldTreatment.allInstructions().size(); index++) {
            instruction = oldTreatment.allInstructions().get(index);
            /*
             * if the action is not optimizable. We simply add
             * to the builder.
             */
            if (checkInstruction(instruction)) {
                treatmentBuilder.add(instruction);
                continue;
            }
            /*
             * We try to run an optimization;
             */
            newInstruction = optimizeInstruction(index, instruction, oldTreatment.allInstructions());
            if (!newInstruction.type().equals(NOACTION)) {
                treatmentBuilder.add(newInstruction);
            }
        }

        return treatmentBuilder.build();
    }

    /**
     * Verifies if the given L2 instruction can be optimized.
     *
     * @param l2instruction the l2 instruction to verify
     * @return true if the instruction cannot be optimized. False otherwise
     */
    private boolean checkL2Instructions(L2ModificationInstruction l2instruction) {
        switch (l2instruction.subtype()) {
            /*
             * These actions can be performed safely.
             */
            case ETH_SRC:
            case ETH_DST:
            case VLAN_ID:
            case VLAN_PCP:
            case MPLS_LABEL:
            case MPLS_BOS:
            case TUNNEL_ID:
            case VLAN_PUSH:
            case VLAN_POP:
            case MPLS_PUSH:
            case MPLS_POP:
                return true;
            /*
             * We should avoid dec mpls ttl multiple
             * times.
             */
            case DEC_MPLS_TTL:
                return false;

            default:
                throw new IntentCompilationException(String.format(UNSUPPORTED_INSTRUCTION, "L2"));
        }

    }

    /**
     * Verifies if the given L3 instruction can be optimized.
     *
     * @param l3instruction the l3 instruction to verify
     * @return true if the instruction cannot be optimized. False otherwise
     */
    private boolean checkL3Instructions(L3ModificationInstruction l3instruction) {
        switch (l3instruction.subtype()) {
            /*
             * These actions can be performed several times.
             */
            case IPV4_SRC:
            case IPV4_DST:
            case IPV6_SRC:
            case IPV6_DST:
            case IPV6_FLABEL:
            case ARP_SPA:
            case ARP_SHA:
            case ARP_OP:
            case TTL_OUT:
            case TTL_IN:
                return true;
            /*
             * This action should be executed one time;
             */
            case DEC_TTL:
                return false;
            default:
                throw new IntentCompilationException(String.format(UNSUPPORTED_INSTRUCTION, "L3"));
        }
    }

    /**
     * Helper method to handle the optimization of the ttl instructions.
     *
     * @param index the index of the instruction
     * @param instruction the instruction to optimize
     * @param instructions the list of instructions to optimize
     * @return no action if the action can be removed. The same instruction
     *         if we have to perform it
     */
    private Instruction optimizeTtlInstructions(int index, Instruction instruction, List<Instruction> instructions) {
        /**
         * Here we handle the optimization of decrement mpls ttl. The optimization
         * is to come back to the start of the list looking for the same
         * action. If we find the same action, we can optimize.
         */
        Instruction currentInstruction;
        for (int i = index - 1; i >= 0; i--) {
            currentInstruction = instructions.get(i);
            if (currentInstruction.equals(instruction)) {
                return Instructions.createNoAction();

            }
        }
        return instruction;
    }

    /**
     * Helper method to handle the optimization of the instructions.
     *
     * @param index the index of the instruction
     * @param instruction the instruction to optimize
     * @param instructions the list of instructions to optimize
     * @return no action if the action can be removed. The same instruction
     *         if we have to perform it
     */
    private Instruction optimizeInstruction(int index, Instruction instruction, List<Instruction> instructions) {

        switch (instruction.type()) {
            /*
             * Here we have the chance to optimize the dec mpls ttl action.
             */
            case L2MODIFICATION:
            /*
             * Here we have the chance to optimize the ttl related actions.
             */
            case L3MODIFICATION:
                return optimizeTtlInstructions(index, instruction, instructions);

            default:
                throw new IntentCompilationException(UNKNOWN_INSTRUCTION);

        }

    }

    /**
     * Helper method to verify if the instruction can be optimized.
     *
     * @param instruction the instruction to verify
     * @return true if the action can be optimized. False otherwise.
     */
    private boolean checkInstruction(Instruction instruction) {

        switch (instruction.type()) {
            /*
             * The following instructions are not supported.
             */
            case L0MODIFICATION:
            case L1MODIFICATION:
            case L4MODIFICATION:
            case NOACTION:
            case OUTPUT:
            case GROUP:
            case QUEUE:
            case TABLE:
            case METER:
            case METADATA:
            case EXTENSION:
                return true;
            /*
             * Here we have the chance to optimize actions like dec mpls ttl.
             */
            case L2MODIFICATION:
                return checkL2Instructions((L2ModificationInstruction) instruction);
            /*
             * Here we have the chance to optimize the ttl related actions.
             */
            case L3MODIFICATION:
                return checkL3Instructions((L3ModificationInstruction) instruction);

            default:
                throw new IntentCompilationException(UNKNOWN_INSTRUCTION);

        }

    }

}
