/*
 * 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.PiCounterCellData;
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.slf4j.Logger;
import p4.config.v1.P4InfoOuterClass;
import p4.v1.P4RuntimeOuterClass.Action;
import p4.v1.P4RuntimeOuterClass.CounterData;
import p4.v1.P4RuntimeOuterClass.FieldMatch;
import p4.v1.P4RuntimeOuterClass.TableAction;
import p4.v1.P4RuntimeOuterClass.TableEntry;

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

import static com.google.common.base.Preconditions.checkNotNull;
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, an EncodeException is thrown.
     *
     * @param piTableEntries PI table entries
     * @param pipeconf       PI pipeconf
     * @return collection of P4Runtime table entry protobuf messages
     * @throws EncodeException if a PI table entry cannot be encoded
     */
    static List<TableEntry> encode(List<PiTableEntry> piTableEntries,
                                                PiPipeconf pipeconf)
            throws EncodeException {

        P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);

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

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

        for (PiTableEntry piTableEntry : piTableEntries) {
            try {
                tableEntryMsgListBuilder.add(encodePiTableEntry(piTableEntry, browser));
            } catch (P4InfoBrowser.NotFoundException e) {
                throw new EncodeException(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 List<PiTableEntry> decode(List<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.
        if (matchKey.equals(PiMatchKey.EMPTY)) {
            tableEntryMsgBuilder.setIsDefaultAction(true);
        } else {
            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.
        piTableEntry.priority().ifPresent(tableEntryMsgBuilder::setPriority);

        // 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.
        if (piTableEntry.action() != null) {
            tableEntryMsgBuilder.setAction(encodePiTableAction(piTableEntry.action(), browser));
        }

        // Field matches.
        if (piTableEntry.matchKey().equals(PiMatchKey.EMPTY)) {
            tableEntryMsgBuilder.setIsDefaultAction(true);
        } else {
            for (PiFieldMatch piFieldMatch : piTableEntry.matchKey().fieldMatches()) {
                tableEntryMsgBuilder.addMatch(encodePiFieldMatch(piFieldMatch, tableInfo, browser));
            }
        }

        // Counter.
        if (piTableEntry.counter() != null) {
            tableEntryMsgBuilder.setCounterData(encodeCounter(piTableEntry.counter()));
        }

        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.
        if (tableEntryMsg.getPriority() > 0) {
            piTableEntryBuilder.withPriority(tableEntryMsg.getPriority());
        }

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

        // Table action.
        if (tableEntryMsg.hasAction()) {
            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));

        // Counter.
        piTableEntryBuilder.withCounterCellData(decodeCounter(tableEntryMsg.getCounterData()));

        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();
            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());
        if (tableEntryMsg.getMatchCount() == 0) {
            return PiMatchKey.EMPTY;
        } else {
            return decodeFieldMatchMsgs(tableEntryMsg.getMatchList(), tableInfo, browser);
        }
    }

    private static PiMatchKey decodeFieldMatchMsgs(List<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);
            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 {
        checkNotNull(piTableAction, "Cannot encode null PiTableAction");
        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);
            case ACTION_PROFILE_GROUP_ID:
                return PiActionGroupId.of(tableActionMsg.getActionProfileGroupId());
            case ACTION_PROFILE_MEMBER_ID:
                return PiActionGroupMemberId.of(tableActionMsg.getActionProfileMemberId());
            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();
    }

    static CounterData encodeCounter(PiCounterCellData piCounterCellData) {
        return CounterData.newBuilder().setPacketCount(piCounterCellData.packets())
                .setByteCount(piCounterCellData.bytes()).build();
    }

    static PiCounterCellData decodeCounter(CounterData counterData) {
        return new PiCounterCellData(counterData.getPacketCount(), counterData.getByteCount());
    }
}