/*
 * 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.PiActionParam;
import org.onosproject.net.pi.runtime.PiActionProfileGroupId;
import org.onosproject.net.pi.runtime.PiActionProfileMemberId;
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.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 CodecException if a PI table entry cannot be encoded
     */
    static List<TableEntry> encode(List<PiTableEntry> piTableEntries,
                                                PiPipeconf pipeconf)
            throws CodecException {

        P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);

        if (browser == null) {
            throw new CodecException(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 CodecException(e.getMessage());
            }
        }

        return tableEntryMsgListBuilder.build();
    }

    /**
     * Same as {@link #encode(List, PiPipeconf)} but encodes only one entry.
     *
     * @param piTableEntry table entry
     * @param pipeconf     pipeconf
     * @return encoded table entry message
     * @throws CodecException                 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 CodecException, P4InfoBrowser.NotFoundException {

        P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
        if (browser == null) {
            throw new CodecException(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 | CodecException e) {
                log.error("Unable to decode table entry message: {}", e.getMessage());
            }
        }

        return piTableEntryListBuilder.build();
    }

    /**
     * Same as {@link #decode(List, PiPipeconf)} but decodes only one entry.
     *
     * @param tableEntryMsg table entry message
     * @param pipeconf      pipeconf
     * @return decoded PI table entry
     * @throws CodecException                 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 CodecException, P4InfoBrowser.NotFoundException {

        P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
        if (browser == null) {
            throw new CodecException(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 CodecException                 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 CodecException, 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, CodecException {

        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, CodecException {

        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, CodecException {

        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 CodecException(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 CodecException                 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, CodecException {
        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, CodecException {
        // 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, CodecException {

        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 CodecException(format(
                        "Decoding of field match type '%s' not implemented", typeCase.name()));
        }
    }

    static TableAction encodePiTableAction(PiTableAction piTableAction, P4InfoBrowser browser)
            throws P4InfoBrowser.NotFoundException, CodecException {
        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_PROFILE_GROUP_ID:
                PiActionProfileGroupId actionGroupId = (PiActionProfileGroupId) piTableAction;
                tableActionMsgBuilder.setActionProfileGroupId(actionGroupId.id());
                break;
            case ACTION_PROFILE_MEMBER_ID:
                PiActionProfileMemberId actionProfileMemberId = (PiActionProfileMemberId) piTableAction;
                tableActionMsgBuilder.setActionProfileMemberId(actionProfileMemberId.id());
                break;
            default:
                throw new CodecException(
                        format("Building of table action type %s not implemented", piTableAction.type()));
        }

        return tableActionMsgBuilder.build();
    }

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

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

        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());
    }
}
