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

package org.onosproject.net.pi.impl;

import org.apache.commons.lang3.tuple.Pair;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.net.pi.model.PiMatchType;

import java.util.Optional;

import static org.onlab.util.ImmutableByteSequence.ByteSequenceTrimException;
import static org.onlab.util.ImmutableByteSequence.fit;

/**
 * Abstract implementation of a criterion translator that opportunistically tries to generate different types of match
 * based on an initialization method. It throws an exception when a safe translation is not possible, e.g. when trying
 * to translate a masked criterion to an exact match.
 */
abstract class AbstractCriterionTranslator implements CriterionTranslator {

    private PiMatchType initType;
    private int bitWidth;
    private ImmutableByteSequence value;
    private ImmutableByteSequence mask;
    private Integer prefixLength;

    /**
     * Initializes the translator as an exact match.
     *
     * @param value     exact match value
     * @param bitWidth  field bit-width
     * @throws ByteSequenceTrimException if the match value cannot be trimmed to fit the field match bit-width
     */
    void initAsExactMatch(ImmutableByteSequence value, int bitWidth)
            throws ByteSequenceTrimException {
        this.initType = PiMatchType.EXACT;
        this.value = fit(value, bitWidth);
        this.bitWidth = bitWidth;
    }

    /**
     * Initializes the translator as a ternary match.
     *
     * @param value     match value
     * @param mask      match mask
     * @param bitWidth  field bit-width
     * @throws ByteSequenceTrimException if the match value or mask cannot be trimmed to fit the field match bit-width
     */
    void initAsTernaryMatch(ImmutableByteSequence value, ImmutableByteSequence mask, int bitWidth)
            throws ByteSequenceTrimException {
        this.initType = PiMatchType.TERNARY;
        this.value = fit(value, bitWidth);
        this.mask = fit(mask, bitWidth);
        this.bitWidth = bitWidth;
    }

    /**
     * Initializes the translator as a longest-prefix match.
     *
     * @param value        match value
     * @param prefixLength prefix length
     * @param bitWidth     field bit-width
     * @throws ByteSequenceTrimException if the match value cannot be trimmed to fit the field match bit-width
     */
    void initAsLpm(ImmutableByteSequence value, int prefixLength, int bitWidth)
            throws ByteSequenceTrimException {
        this.initType = PiMatchType.LPM;
        this.value = fit(value, bitWidth);
        this.prefixLength = prefixLength;
        this.bitWidth = bitWidth;
    }

    /**
     * Computes the prefix padding size (in bits) based on value and bit width.
     *
     * @return prefix padding in bits
     */
    private int prefixPadding() {
        return value.size() * Byte.SIZE - this.bitWidth;
    }

    @Override
    public ImmutableByteSequence exactMatch() throws CriterionTranslatorException {
        switch (initType) {
            case EXACT:
                break;
            case TERNARY:
                ImmutableByteSequence exactMask = ImmutableByteSequence.ofOnes(value.size());
                if (!mask.equals(exactMask)) {
                    throw new CriterionTranslator.CriterionTranslatorException(
                            "trying to use masked field as an exact match, but mask is not exact");
                }
                break;
            case LPM:
                if (prefixLength < bitWidth) {
                    throw new CriterionTranslator.CriterionTranslatorException(
                            "trying to use LPM field as an exact match, but prefix is not full");
                }
                break;
            default:
                throw new RuntimeException("Unrecognized init type " + initType.name());
        }
        return value;
    }

    @Override
    public Pair<ImmutableByteSequence, ImmutableByteSequence> ternaryMatch() {
        switch (initType) {
            case EXACT:
                mask = ImmutableByteSequence.prefixZeros(value.size(), prefixPadding());
                break;
            case TERNARY:
                break;
            case LPM:
                mask = getMaskFromPrefixLength(prefixLength, value.size());
            default:
                throw new RuntimeException("Unrecognized init type " + initType.name());
        }

        return Pair.of(value, mask);
    }

    @Override
    public Pair<ImmutableByteSequence, Integer> lpmMatch() throws CriterionTranslatorException {
        switch (initType) {
            case EXACT:
                prefixLength = bitWidth;
                break;
            case TERNARY:
                prefixLength = getPrefixLengthFromMask(mask).orElseThrow(
                        () -> new CriterionTranslatorException(
                                "trying to use masked field as a longest-prefix match, " +
                                        "but mask is not equivalent to a prefix length"));
                break;
            case LPM:
                break;
            default:
                throw new RuntimeException("Unrecognized init type " + initType.name());
        }

        return Pair.of(value, prefixLength);
    }

    /**
     * Returns a bit mask equivalent to the given prefix length.
     *
     * @param prefixLength prefix length (in bits)
     * @param maskSize     mask size (in bytes)
     * @return a byte sequence
     */
    private ImmutableByteSequence getMaskFromPrefixLength(int prefixLength, int maskSize) {
        // TODO: implement.
        throw new RuntimeException("getMaskFromPrefixLength() not implemented yet.");
    }

    /**
     * Checks that the given mask is equivalent to a longest-prefix match and returns the prefix length. If not
     * possible, the optional value will not be present.
     *
     * @param mask byte sequence
     * @return optional prefix length
     */
    private Optional<Integer> getPrefixLengthFromMask(ImmutableByteSequence mask) {
        // TODO: implement.
        throw new RuntimeException("getPrefixLengthFromMask() not implemented yet.");
    }
}
