/*
 * 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.p4runtime.ctl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.protobuf.ByteString;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionGroupId;
import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
import org.onosproject.net.pi.runtime.PiActionId;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.net.pi.runtime.PiActionParamId;
import org.onosproject.net.pi.runtime.PiExactFieldMatch;
import org.onosproject.net.pi.runtime.PiFieldMatch;
import org.onosproject.net.pi.runtime.PiHeaderFieldId;
import org.onosproject.net.pi.runtime.PiLpmFieldMatch;
import org.onosproject.net.pi.runtime.PiMatchKey;
import org.onosproject.net.pi.runtime.PiRangeFieldMatch;
import org.onosproject.net.pi.runtime.PiTableAction;
import org.onosproject.net.pi.runtime.PiTableEntry;
import org.onosproject.net.pi.runtime.PiTableId;
import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
import org.onosproject.net.pi.runtime.PiValidFieldMatch;
import org.slf4j.Logger;
import p4.P4RuntimeOuterClass.Action;
import p4.P4RuntimeOuterClass.FieldMatch;
import p4.P4RuntimeOuterClass.TableAction;
import p4.P4RuntimeOuterClass.TableEntry;
import p4.config.P4InfoOuterClass;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

import static java.lang.String.format;
import static org.onlab.util.ImmutableByteSequence.copyFrom;
import static org.onosproject.p4runtime.ctl.P4RuntimeUtils.assertPrefixLen;
import static org.onosproject.p4runtime.ctl.P4RuntimeUtils.assertSize;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Encoder/Decoder of table entries, from ONOS Pi* format, to P4Runtime protobuf messages, and vice versa.
 */
final class TableEntryEncoder {
    private static final Logger log = getLogger(TableEntryEncoder.class);

    private static final String VALUE_OF_PREFIX = "value of ";
    private static final String MASK_OF_PREFIX = "mask of ";
    private static final String HIGH_RANGE_VALUE_OF_PREFIX = "high range value of ";
    private static final String LOW_RANGE_VALUE_OF_PREFIX = "low range value of ";

    // TODO: implement cache of encoded entities.

    private TableEntryEncoder() {
        // hide.
    }

    /**
     * Returns a collection of P4Runtime table entry protobuf messages, encoded from the given collection of PI table
     * entries for the given pipeconf. If a PI table entry cannot be encoded, it is skipped, hence the returned
     * collection might have different size than the input one.
     * <p>
     * Please check the log for an explanation of any error that might have occurred.
     *
     * @param piTableEntries PI table entries
     * @param pipeconf       PI pipeconf
     * @return collection of P4Runtime table entry protobuf messages
     */
    static Collection<TableEntry> encode(Collection<PiTableEntry> piTableEntries, PiPipeconf pipeconf) {

        P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);

        if (browser == null) {
            log.error("Unable to get a P4Info browser for pipeconf {}, skipping encoding of all table entries");
            return Collections.emptyList();
        }

        ImmutableList.Builder<TableEntry> tableEntryMsgListBuilder = ImmutableList.builder();

        for (PiTableEntry piTableEntry : piTableEntries) {
            try {
                tableEntryMsgListBuilder.add(encodePiTableEntry(piTableEntry, browser));
            } catch (P4InfoBrowser.NotFoundException | EncodeException e) {
                log.error("Unable to encode PI table entry: {}", e.getMessage());
            }
        }

        return tableEntryMsgListBuilder.build();
    }

    /**
     * Same as {@link #encode(Collection, PiPipeconf)} but encodes only one entry.
     *
     * @param piTableEntry table entry
     * @param pipeconf     pipeconf
     * @return encoded table entry message
     * @throws EncodeException                 if entry cannot be encoded
     * @throws P4InfoBrowser.NotFoundException if the required information cannot be find in the pipeconf's P4info
     */
    static TableEntry encode(PiTableEntry piTableEntry, PiPipeconf pipeconf)
            throws EncodeException, P4InfoBrowser.NotFoundException {

        P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
        if (browser == null) {
            throw new EncodeException(format("Unable to get a P4Info browser for pipeconf %s", pipeconf.id()));
        }

        return encodePiTableEntry(piTableEntry, browser);
    }

    /**
     * Returns a collection of PI table entry objects, decoded from the given collection of P4Runtime table entry
     * messages for the given pipeconf. If a table entry message cannot be decoded, it is skipped, hence the returned
     * collection might have different size than the input one.
     * <p>
     * Please check the log for an explanation of any error that might have occurred.
     *
     * @param tableEntryMsgs P4Runtime table entry messages
     * @param pipeconf       PI pipeconf
     * @return collection of PI table entry objects
     */
    static Collection<PiTableEntry> decode(Collection<TableEntry> tableEntryMsgs, PiPipeconf pipeconf) {

        P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);

        if (browser == null) {
            log.error("Unable to get a P4Info browser for pipeconf {}, skipping decoding of all table entries");
            return Collections.emptyList();
        }

        ImmutableList.Builder<PiTableEntry> piTableEntryListBuilder = ImmutableList.builder();

        for (TableEntry tableEntryMsg : tableEntryMsgs) {
            try {
                piTableEntryListBuilder.add(decodeTableEntryMsg(tableEntryMsg, browser));
            } catch (P4InfoBrowser.NotFoundException | EncodeException e) {
                log.error("Unable to decode table entry message: {}", e.getMessage());
            }
        }

        return piTableEntryListBuilder.build();
    }

    /**
     * Same as {@link #decode(Collection, PiPipeconf)} but decodes only one entry.
     *
     * @param tableEntryMsg table entry message
     * @param pipeconf      pipeconf
     * @return decoded PI table entry
     * @throws EncodeException                 if message cannot be decoded
     * @throws P4InfoBrowser.NotFoundException if the required information cannot be find in the pipeconf's P4info
     */
    static PiTableEntry decode(TableEntry tableEntryMsg, PiPipeconf pipeconf)
            throws EncodeException, P4InfoBrowser.NotFoundException {

        P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
        if (browser == null) {
            throw new EncodeException(format("Unable to get a P4Info browser for pipeconf %s", pipeconf.id()));
        }
        return decodeTableEntryMsg(tableEntryMsg, browser);
    }

    /**
     * Returns a table entry protobuf message, encoded from the given table id and match key, for the given pipeconf.
     * The returned table entry message can be only used to reference an existing entry, i.e. a read operation, and not
     * a write one wince it misses other fields (action, priority, etc.).
     *
     * @param tableId  table identifier
     * @param matchKey match key
     * @param pipeconf pipeconf
     * @return table entry message
     * @throws EncodeException                 if message cannot be encoded
     * @throws P4InfoBrowser.NotFoundException if the required information cannot be find in the pipeconf's P4info
     */
    static TableEntry encode(PiTableId tableId, PiMatchKey matchKey, PiPipeconf pipeconf)
            throws EncodeException, P4InfoBrowser.NotFoundException {

        P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
        TableEntry.Builder tableEntryMsgBuilder = TableEntry.newBuilder();

        P4InfoOuterClass.Table tableInfo = browser.tables().getByName(tableId.id());

        // Table id.
        tableEntryMsgBuilder.setTableId(tableInfo.getPreamble().getId());

        // Field matches.
        for (PiFieldMatch piFieldMatch : matchKey.fieldMatches()) {
            tableEntryMsgBuilder.addMatch(encodePiFieldMatch(piFieldMatch, tableInfo, browser));
        }

        return tableEntryMsgBuilder.build();
    }

    private static TableEntry encodePiTableEntry(PiTableEntry piTableEntry, P4InfoBrowser browser)
            throws P4InfoBrowser.NotFoundException, EncodeException {

        TableEntry.Builder tableEntryMsgBuilder = TableEntry.newBuilder();

        P4InfoOuterClass.Table tableInfo = browser.tables().getByName(piTableEntry.table().id());

        // Table id.
        tableEntryMsgBuilder.setTableId(tableInfo.getPreamble().getId());

        // Priority.
        // FIXME: check on P4Runtime if/what is the default priority.
        int priority = piTableEntry.priority().orElse(0);
        tableEntryMsgBuilder.setPriority(priority);

        // Controller metadata (cookie)
        tableEntryMsgBuilder.setControllerMetadata(piTableEntry.cookie());

        // Timeout.
        if (piTableEntry.timeout().isPresent()) {
            log.warn("Found PI table entry with timeout set, not supported in P4Runtime: {}", piTableEntry);
        }

        // Table action.
        tableEntryMsgBuilder.setAction(encodePiTableAction(piTableEntry.action(), browser));

        // Field matches.
        for (PiFieldMatch piFieldMatch : piTableEntry.matchKey().fieldMatches()) {
            tableEntryMsgBuilder.addMatch(encodePiFieldMatch(piFieldMatch, tableInfo, browser));
        }

        return tableEntryMsgBuilder.build();
    }

    private static PiTableEntry decodeTableEntryMsg(TableEntry tableEntryMsg, P4InfoBrowser browser)
            throws P4InfoBrowser.NotFoundException, EncodeException {

        PiTableEntry.Builder piTableEntryBuilder = PiTableEntry.builder();

        P4InfoOuterClass.Table tableInfo = browser.tables().getById(tableEntryMsg.getTableId());

        // Table id.
        piTableEntryBuilder.forTable(PiTableId.of(tableInfo.getPreamble().getName()));

        // Priority.
        piTableEntryBuilder.withPriority(tableEntryMsg.getPriority());

        // Controller metadata (cookie)
        piTableEntryBuilder.withCookie(tableEntryMsg.getControllerMetadata());

        // Table action.
        piTableEntryBuilder.withAction(decodeTableActionMsg(tableEntryMsg.getAction(), browser));

        // Timeout.
        // FIXME: how to decode table entry messages with timeout, given that the timeout value is lost after encoding?

        // Match key for field matches.
        piTableEntryBuilder.withMatchKey(decodeFieldMatchMsgs(tableEntryMsg.getMatchList(), tableInfo, browser));

        return piTableEntryBuilder.build();
    }

    private static FieldMatch encodePiFieldMatch(PiFieldMatch piFieldMatch, P4InfoOuterClass.Table tableInfo,
                                                 P4InfoBrowser browser)
            throws P4InfoBrowser.NotFoundException, EncodeException {

        FieldMatch.Builder fieldMatchMsgBuilder = FieldMatch.newBuilder();

        // FIXME: check how field names for stacked headers are constructed in P4Runtime.
        String fieldName = piFieldMatch.fieldId().id();
        int tableId = tableInfo.getPreamble().getId();
        P4InfoOuterClass.MatchField matchFieldInfo = browser.matchFields(tableId).getByName(fieldName);
        String entityName = format("field match '%s' of table '%s'",
                                   matchFieldInfo.getName(), tableInfo.getPreamble().getName());
        int fieldId = matchFieldInfo.getId();
        int fieldBitwidth = matchFieldInfo.getBitwidth();

        fieldMatchMsgBuilder.setFieldId(fieldId);

        switch (piFieldMatch.type()) {
            case EXACT:
                PiExactFieldMatch fieldMatch = (PiExactFieldMatch) piFieldMatch;
                ByteString exactValue = ByteString.copyFrom(fieldMatch.value().asReadOnlyBuffer());
                assertSize(VALUE_OF_PREFIX + entityName, exactValue, fieldBitwidth);
                return fieldMatchMsgBuilder.setExact(
                        FieldMatch.Exact
                                .newBuilder()
                                .setValue(exactValue)
                                .build())
                        .build();
            case TERNARY:
                PiTernaryFieldMatch ternaryMatch = (PiTernaryFieldMatch) piFieldMatch;
                ByteString ternaryValue = ByteString.copyFrom(ternaryMatch.value().asReadOnlyBuffer());
                ByteString ternaryMask = ByteString.copyFrom(ternaryMatch.mask().asReadOnlyBuffer());
                assertSize(VALUE_OF_PREFIX + entityName, ternaryValue, fieldBitwidth);
                assertSize(MASK_OF_PREFIX + entityName, ternaryMask, fieldBitwidth);
                return fieldMatchMsgBuilder.setTernary(
                        FieldMatch.Ternary
                                .newBuilder()
                                .setValue(ternaryValue)
                                .setMask(ternaryMask)
                                .build())
                        .build();
            case LPM:
                PiLpmFieldMatch lpmMatch = (PiLpmFieldMatch) piFieldMatch;
                ByteString lpmValue = ByteString.copyFrom(lpmMatch.value().asReadOnlyBuffer());
                int lpmPrefixLen = lpmMatch.prefixLength();
                assertSize(VALUE_OF_PREFIX + entityName, lpmValue, fieldBitwidth);
                assertPrefixLen(entityName, lpmPrefixLen, fieldBitwidth);
                return fieldMatchMsgBuilder.setLpm(
                        FieldMatch.LPM.newBuilder()
                                .setValue(lpmValue)
                                .setPrefixLen(lpmPrefixLen)
                                .build())
                        .build();
            case RANGE:
                PiRangeFieldMatch rangeMatch = (PiRangeFieldMatch) piFieldMatch;
                ByteString rangeHighValue = ByteString.copyFrom(rangeMatch.highValue().asReadOnlyBuffer());
                ByteString rangeLowValue = ByteString.copyFrom(rangeMatch.lowValue().asReadOnlyBuffer());
                assertSize(HIGH_RANGE_VALUE_OF_PREFIX + entityName, rangeHighValue, fieldBitwidth);
                assertSize(LOW_RANGE_VALUE_OF_PREFIX + entityName, rangeLowValue, fieldBitwidth);
                return fieldMatchMsgBuilder.setRange(
                        FieldMatch.Range.newBuilder()
                                .setHigh(rangeHighValue)
                                .setLow(rangeLowValue)
                                .build())
                        .build();
            case VALID:
                PiValidFieldMatch validMatch = (PiValidFieldMatch) piFieldMatch;
                return fieldMatchMsgBuilder.setValid(
                        FieldMatch.Valid.newBuilder()
                                .setValue(validMatch.isValid())
                                .build())
                        .build();
            default:
                throw new EncodeException(format(
                        "Building of match type %s not implemented", piFieldMatch.type()));
        }
    }

    /**
     * Returns a PI match key, decoded from the given table entry protobuf message, for the given pipeconf.
     *
     * @param tableEntryMsg table entry message
     * @param pipeconf      pipeconf
     * @return PI match key
     * @throws EncodeException                 if message cannot be decoded
     * @throws P4InfoBrowser.NotFoundException if the required information cannot be find in the pipeconf's P4info
     */
    static PiMatchKey decodeMatchKey(TableEntry tableEntryMsg, PiPipeconf pipeconf)
            throws P4InfoBrowser.NotFoundException, EncodeException {
        P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
        P4InfoOuterClass.Table tableInfo = browser.tables().getById(tableEntryMsg.getTableId());
        return decodeFieldMatchMsgs(tableEntryMsg.getMatchList(), tableInfo, browser);
    }

    private static PiMatchKey decodeFieldMatchMsgs(Collection<FieldMatch> fieldMatchs, P4InfoOuterClass.Table tableInfo,
                                                   P4InfoBrowser browser)
            throws P4InfoBrowser.NotFoundException, EncodeException {
        // Match key for field matches.
        PiMatchKey.Builder piMatchKeyBuilder = PiMatchKey.builder();
        for (FieldMatch fieldMatchMsg : fieldMatchs) {
            piMatchKeyBuilder.addFieldMatch(decodeFieldMatchMsg(fieldMatchMsg, tableInfo, browser));
        }
        return piMatchKeyBuilder.build();
    }

    private static PiFieldMatch decodeFieldMatchMsg(FieldMatch fieldMatchMsg, P4InfoOuterClass.Table tableInfo,
                                                    P4InfoBrowser browser)
            throws P4InfoBrowser.NotFoundException, EncodeException {

        int tableId = tableInfo.getPreamble().getId();
        String fieldMatchName = browser.matchFields(tableId).getById(fieldMatchMsg.getFieldId()).getName();

        // FIXME: nasty hack needed to provide compatibility with BMv2-based pipeline models.
        // Indeed in the BMv2 JSON header fields have format like "ethernet.srd_addr", while in P4Info
        // the same will be "hdr.ethernet.srd_addr".
        // To be removed when ONOS-7066 will be implemented.
        fieldMatchName = P4InfoBrowser.extractMatchFieldSimpleName(fieldMatchName);

        // FIXME: Add support for decoding of stacked header names.
        String[] pieces = fieldMatchName.split("\\.");
        if (pieces.length != 2) {
            throw new EncodeException(format("unrecognized field match name '%s'", fieldMatchName));
        }
        PiHeaderFieldId headerFieldId = PiHeaderFieldId.of(pieces[0], pieces[1]);

        FieldMatch.FieldMatchTypeCase typeCase = fieldMatchMsg.getFieldMatchTypeCase();

        switch (typeCase) {
            case EXACT:
                FieldMatch.Exact exactFieldMatch = fieldMatchMsg.getExact();
                ImmutableByteSequence exactValue = copyFrom(exactFieldMatch.getValue().asReadOnlyByteBuffer());
                return new PiExactFieldMatch(headerFieldId, exactValue);
            case TERNARY:
                FieldMatch.Ternary ternaryFieldMatch = fieldMatchMsg.getTernary();
                ImmutableByteSequence ternaryValue = copyFrom(ternaryFieldMatch.getValue().asReadOnlyByteBuffer());
                ImmutableByteSequence ternaryMask = copyFrom(ternaryFieldMatch.getMask().asReadOnlyByteBuffer());
                return new PiTernaryFieldMatch(headerFieldId, ternaryValue, ternaryMask);
            case LPM:
                FieldMatch.LPM lpmFieldMatch = fieldMatchMsg.getLpm();
                ImmutableByteSequence lpmValue = copyFrom(lpmFieldMatch.getValue().asReadOnlyByteBuffer());
                int lpmPrefixLen = lpmFieldMatch.getPrefixLen();
                return new PiLpmFieldMatch(headerFieldId, lpmValue, lpmPrefixLen);
            case RANGE:
                FieldMatch.Range rangeFieldMatch = fieldMatchMsg.getRange();
                ImmutableByteSequence rangeHighValue = copyFrom(rangeFieldMatch.getHigh().asReadOnlyByteBuffer());
                ImmutableByteSequence rangeLowValue = copyFrom(rangeFieldMatch.getLow().asReadOnlyByteBuffer());
                return new PiRangeFieldMatch(headerFieldId, rangeLowValue, rangeHighValue);
            case VALID:
                FieldMatch.Valid validFieldMatch = fieldMatchMsg.getValid();
                return new PiValidFieldMatch(headerFieldId, validFieldMatch.getValue());
            default:
                throw new EncodeException(format(
                        "Decoding of field match type '%s' not implemented", typeCase.name()));
        }
    }

    static TableAction encodePiTableAction(PiTableAction piTableAction, P4InfoBrowser browser)
            throws P4InfoBrowser.NotFoundException, EncodeException {

        TableAction.Builder tableActionMsgBuilder = TableAction.newBuilder();

        switch (piTableAction.type()) {
            case ACTION:
                PiAction piAction = (PiAction) piTableAction;
                Action theAction = encodePiAction(piAction, browser);
                tableActionMsgBuilder.setAction(theAction);
                break;
            case ACTION_GROUP_ID:
                PiActionGroupId actionGroupId = (PiActionGroupId) piTableAction;
                tableActionMsgBuilder.setActionProfileGroupId(actionGroupId.id());
                break;
            case GROUP_MEMBER_ID:
                PiActionGroupMemberId actionGroupMemberId = (PiActionGroupMemberId) piTableAction;
                tableActionMsgBuilder.setActionProfileMemberId(actionGroupMemberId.id());
                break;
            default:
                throw new EncodeException(
                        format("Building of table action type %s not implemented", piTableAction.type()));
        }

        return tableActionMsgBuilder.build();
    }

    static PiTableAction decodeTableActionMsg(TableAction tableActionMsg, P4InfoBrowser browser)
            throws P4InfoBrowser.NotFoundException, EncodeException {
        TableAction.TypeCase typeCase = tableActionMsg.getTypeCase();
        switch (typeCase) {
            case ACTION:
                Action actionMsg = tableActionMsg.getAction();
                return decodeActionMsg(actionMsg, browser);
            default:
                throw new EncodeException(
                        format("Decoding of table action type %s not implemented", typeCase.name()));
        }
    }

    static Action encodePiAction(PiAction piAction, P4InfoBrowser browser)
            throws P4InfoBrowser.NotFoundException, EncodeException {

        int actionId = browser.actions().getByName(piAction.id().name()).getPreamble().getId();

        Action.Builder actionMsgBuilder =
                Action.newBuilder().setActionId(actionId);

        for (PiActionParam p : piAction.parameters()) {
            P4InfoOuterClass.Action.Param paramInfo = browser.actionParams(actionId).getByName(p.id().name());
            ByteString paramValue = ByteString.copyFrom(p.value().asReadOnlyBuffer());
            assertSize(format("param '%s' of action '%s'", p.id(), piAction.id()),
                       paramValue, paramInfo.getBitwidth());
            actionMsgBuilder.addParams(Action.Param.newBuilder()
                                               .setParamId(paramInfo.getId())
                                               .setValue(paramValue)
                                               .build());
        }

        return actionMsgBuilder.build();
    }

    static PiAction decodeActionMsg(Action action, P4InfoBrowser browser)
            throws P4InfoBrowser.NotFoundException {
        P4InfoBrowser.EntityBrowser<P4InfoOuterClass.Action.Param> paramInfo =
                browser.actionParams(action.getActionId());
        String actionName = browser.actions()
                .getById(action.getActionId())
                .getPreamble().getName();
        PiActionId id = PiActionId.of(actionName);
        List<PiActionParam> params = Lists.newArrayList();

        for (Action.Param p : action.getParamsList()) {
            String paramName = paramInfo.getById(p.getParamId()).getName();
            ImmutableByteSequence value = ImmutableByteSequence.copyFrom(p.getValue().toByteArray());
            params.add(new PiActionParam(PiActionParamId.of(paramName), value));
        }
        return PiAction.builder().withId(id).withParameters(params).build();
    }
}
