/*
 * 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.PiActionId;
import org.onosproject.net.pi.model.PiActionParamId;
import org.onosproject.net.pi.model.PiMatchFieldId;
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.model.PiTableId;
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.PiActionParam;
import org.onosproject.net.pi.runtime.PiExactFieldMatch;
import org.onosproject.net.pi.runtime.PiFieldMatch;
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.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();
        PiMatchFieldId headerFieldId = PiMatchFieldId.of(fieldMatchName);

        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().toString()).getPreamble().getId();

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

        for (PiActionParam p : piAction.parameters()) {
            P4InfoOuterClass.Action.Param paramInfo = browser.actionParams(actionId).getByName(p.id().toString());
            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();
    }
}
