/*
 * Copyright 2016-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.drivers.bmv2.translators;

import com.google.common.annotations.Beta;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.bmv2.api.model.Bmv2Model;
import org.onosproject.bmv2.api.model.Bmv2ModelField;
import org.onosproject.bmv2.api.model.Bmv2ModelTable;
import org.onosproject.bmv2.api.model.Bmv2ModelTableKey;
import org.onosproject.bmv2.api.runtime.Bmv2Action;
import org.onosproject.bmv2.api.runtime.Bmv2ExtensionSelector;
import org.onosproject.bmv2.api.runtime.Bmv2ExtensionTreatment;
import org.onosproject.bmv2.api.runtime.Bmv2LpmMatchParam;
import org.onosproject.bmv2.api.runtime.Bmv2MatchKey;
import org.onosproject.bmv2.api.runtime.Bmv2TableEntry;
import org.onosproject.bmv2.api.runtime.Bmv2TernaryMatchParam;
import org.onosproject.net.flow.FlowRule;
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.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.ExtensionCriterion;
import org.onosproject.net.flow.criteria.ExtensionSelector;
import org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.instructions.ExtensionTreatment;
import org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.Instructions.ExtensionInstructionWrapper;

/**
 * Default Bmv2 flow rule translator implementation.
 * <p>
 * Flow rules are translated into {@link Bmv2TableEntry BMv2 table entries} according to the following logic:
 * <ul>
 * <li> table name: obtained from the Bmv2 model using the flow rule table ID;
 * <li> match key: if the flow rule selector defines only a criterion of type {@link Criterion.Type#EXTENSION EXTENSION}
 * , then the latter is expected to contain a {@link Bmv2ExtensionSelector Bmv2ExtensionSelector}, which should provide
 * a match key already formatted for the given table; otherwise a match key is built using the
 * {@link TranslatorConfig#fieldToCriterionTypeMap() mapping} defined by this translator configuration.
 * <li> action: if the flow rule treatment contains only one instruction of type
 * {@link Instruction.Type#EXTENSION EXTENSION}, then the latter is expected to contain a {@link Bmv2ExtensionTreatment}
 * , which should provide a {@link Bmv2Action} already formatted for the given table; otherwise, an action is
 * {@link TranslatorConfig#buildAction(TrafficTreatment) built} using this translator configuration.
 * <li> priority: the same as the flow rule.
 * <li> timeout: if the table supports timeout, use the same as the flow rule, otherwise none (i.e. permanent entry).
 * </ul>
 */
@Beta
public class Bmv2DefaultFlowRuleTranslator implements Bmv2FlowRuleTranslator {

    // TODO: config is harcoded now, instead it should be selected based on device model
    private final TranslatorConfig config = new Bmv2SimpleTranslatorConfig();
    private final Bmv2Model model = config.model();

    private static Bmv2TernaryMatchParam buildTernaryParam(Bmv2ModelField field, Criterion criterion, int byteWidth)
            throws Bmv2FlowRuleTranslatorException {

        // Value and mask will be filled according to criterion type
        ImmutableByteSequence value;
        ImmutableByteSequence mask = null;

        switch (criterion.type()) {
            case IN_PORT:
                // FIXME: allow port numbers of variable bit length (based on model), truncating when necessary
                short port = (short) ((PortCriterion) criterion).port().toLong();
                value = ImmutableByteSequence.copyFrom(port);
                break;
            case ETH_DST:
                EthCriterion c = (EthCriterion) criterion;
                value = ImmutableByteSequence.copyFrom(c.mac().toBytes());
                if (c.mask() != null) {
                    mask = ImmutableByteSequence.copyFrom(c.mask().toBytes());
                }
                break;
            case ETH_SRC:
                EthCriterion c2 = (EthCriterion) criterion;
                value = ImmutableByteSequence.copyFrom(c2.mac().toBytes());
                if (c2.mask() != null) {
                    mask = ImmutableByteSequence.copyFrom(c2.mask().toBytes());
                }
                break;
            case ETH_TYPE:
                short ethType = ((EthTypeCriterion) criterion).ethType().toShort();
                value = ImmutableByteSequence.copyFrom(ethType);
                break;
            // TODO: implement building for other criterion types (easy with DefaultCriterion of ONOS-4034)
            default:
                throw new Bmv2FlowRuleTranslatorException("Feature not implemented, ternary builder for criterion" +
                                                                  "type: " + criterion.type().name());
        }

        if (mask == null) {
            // no mask, all ones
            mask = ImmutableByteSequence.ofOnes(byteWidth);
        }

        return new Bmv2TernaryMatchParam(value, mask);
    }

    private static Bmv2MatchKey getMatchKeyFromExtension(ExtensionCriterion criterion)
            throws Bmv2FlowRuleTranslatorException {

        ExtensionSelector extSelector = criterion.extensionSelector();

        if (extSelector.type() == ExtensionSelectorTypes.P4_BMV2_MATCH_KEY.type()) {
            if (extSelector instanceof Bmv2ExtensionSelector) {
                return ((Bmv2ExtensionSelector) extSelector).matchKey();
            } else {
                throw new Bmv2FlowRuleTranslatorException("Unable to decode extension selector " + extSelector);
            }
        } else {
            throw new Bmv2FlowRuleTranslatorException("Unsupported extension selector type " + extSelector.type());
        }
    }

    private static Bmv2Action getActionFromExtension(Instructions.ExtensionInstructionWrapper inst)
            throws Bmv2FlowRuleTranslatorException {

        ExtensionTreatment extTreatment = inst.extensionInstruction();

        if (extTreatment.type() == ExtensionTreatmentTypes.P4_BMV2_ACTION.type()) {
            if (extTreatment instanceof Bmv2ExtensionTreatment) {
                return ((Bmv2ExtensionTreatment) extTreatment).getAction();
            } else {
                throw new Bmv2FlowRuleTranslatorException("Unable to decode treatment extension: " + extTreatment);
            }
        } else {
            throw new Bmv2FlowRuleTranslatorException("Unsupported treatment extension type: " + extTreatment.type());
        }
    }

    private static Bmv2MatchKey buildMatchKey(TranslatorConfig config, TrafficSelector selector, Bmv2ModelTable table)
            throws Bmv2FlowRuleTranslatorException {

        Bmv2MatchKey.Builder matchKeyBuilder = Bmv2MatchKey.builder();

        for (Bmv2ModelTableKey key : table.keys()) {

            String fieldName = key.field().header().name() + "." + key.field().type().name();
            int byteWidth = (int) Math.ceil((double) key.field().type().bitWidth() / 8.0);
            Criterion.Type criterionType = config.fieldToCriterionTypeMap().get(fieldName);

            if (criterionType == null || selector.getCriterion(criterionType) == null) {
                // A mapping is not available or the selector doesn't have such a type
                switch (key.matchType()) {
                    case TERNARY:
                        // Wildcard field
                        matchKeyBuilder.withWildcard(byteWidth);
                        break;
                    case LPM:
                        // LPM with prefix 0
                        matchKeyBuilder.add(new Bmv2LpmMatchParam(ImmutableByteSequence.ofZeros(byteWidth), 0));
                        break;
                    default:
                        throw new Bmv2FlowRuleTranslatorException("Match field not supported: " + fieldName);
                }
                // Next key
                continue;
            }

            Criterion criterion = selector.getCriterion(criterionType);
            Bmv2TernaryMatchParam matchParam = null;

            switch (key.matchType()) {
                case TERNARY:
                    matchParam = buildTernaryParam(key.field(), criterion, byteWidth);
                    break;
                default:
                    // TODO: implement other match param builders (exact, LPM, etc.)
                    throw new Bmv2FlowRuleTranslatorException("Feature not implemented, match param builder: "
                                                                      + key.matchType().name());
            }

            matchKeyBuilder.add(matchParam);
        }

        return matchKeyBuilder.build();
    }

    @Override
    public Bmv2TableEntry translate(FlowRule rule)
            throws Bmv2FlowRuleTranslatorException {

        int tableId = rule.tableId();

        Bmv2ModelTable table = model.table(tableId);

        if (table == null) {
            throw new Bmv2FlowRuleTranslatorException("Unknown table ID: " + tableId);
        }

        /* Translate selector */

        TrafficSelector selector = rule.selector();
        Bmv2MatchKey bmv2MatchKey = null;

        // If selector has only 1 criterion of type extension, use that
        Criterion criterion = selector.getCriterion(Criterion.Type.EXTENSION);
        if (criterion != null) {
            if (selector.criteria().size() == 1) {
                bmv2MatchKey = getMatchKeyFromExtension((ExtensionCriterion) criterion);
            } else {
                throw new Bmv2FlowRuleTranslatorException("Unable to translate traffic selector, found multiple " +
                                                                  "criteria of which one is an extension: " +
                                                                  selector.toString());
            }
        }

        if (bmv2MatchKey == null) {
            // not an extension
            bmv2MatchKey = buildMatchKey(config, selector, table);
        }

        /* Translate treatment */

        TrafficTreatment treatment = rule.treatment();
        Bmv2Action bmv2Action = null;

        // If treatment has only 1 instruction of type extension, use that
        for (Instruction inst : treatment.allInstructions()) {
            if (inst.type() == Instruction.Type.EXTENSION) {
                if (treatment.allInstructions().size() == 1) {
                    bmv2Action = getActionFromExtension((ExtensionInstructionWrapper) inst);
                } else {
                    throw new Bmv2FlowRuleTranslatorException("Unable to translate traffic treatment, found multiple " +
                                                                      "instructions of which one is an extension: " +
                                                                      selector.toString());
                }
            }
        }

        if (bmv2Action == null) {
            // No extension, use config to build action
            bmv2Action = config.buildAction(treatment);
        }

        if (bmv2Action == null) {
            // Config returned null
            throw new Bmv2FlowRuleTranslatorException("Unable to translate treatment: " + treatment);
        }

        Bmv2TableEntry.Builder tableEntryBuilder = Bmv2TableEntry.builder();

        tableEntryBuilder
                .withTableName(table.name())
                .withPriority(rule.priority())
                .withMatchKey(bmv2MatchKey)
                .withAction(bmv2Action);

        if (!rule.isPermanent()) {
            if (table.hasTimeouts()) {
                tableEntryBuilder.withTimeout((double) rule.timeout());
            }
            //FIXME: add warn log or exception?
        }

        return tableEntryBuilder.build();
    }

    @Override
    public TranslatorConfig config() {
        return this.config;
    }
}
