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

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.hash.Hashing;
import com.google.common.hash.HashingInputStream;
import com.google.protobuf.ExtensionRegistry;
import com.google.protobuf.TextFormat;
import org.onosproject.net.pi.model.PiActionId;
import org.onosproject.net.pi.model.PiActionModel;
import org.onosproject.net.pi.model.PiActionParamId;
import org.onosproject.net.pi.model.PiActionParamModel;
import org.onosproject.net.pi.model.PiActionProfileId;
import org.onosproject.net.pi.model.PiActionProfileModel;
import org.onosproject.net.pi.model.PiCounterId;
import org.onosproject.net.pi.model.PiCounterModel;
import org.onosproject.net.pi.model.PiCounterType;
import org.onosproject.net.pi.model.PiMatchFieldId;
import org.onosproject.net.pi.model.PiMatchFieldModel;
import org.onosproject.net.pi.model.PiMatchType;
import org.onosproject.net.pi.model.PiMeterId;
import org.onosproject.net.pi.model.PiMeterModel;
import org.onosproject.net.pi.model.PiMeterType;
import org.onosproject.net.pi.model.PiPacketMetadataId;
import org.onosproject.net.pi.model.PiPacketMetadataModel;
import org.onosproject.net.pi.model.PiPacketOperationModel;
import org.onosproject.net.pi.model.PiPacketOperationType;
import org.onosproject.net.pi.model.PiPipelineModel;
import org.onosproject.net.pi.model.PiRegisterId;
import org.onosproject.net.pi.model.PiRegisterModel;
import org.onosproject.net.pi.model.PiTableId;
import org.onosproject.net.pi.model.PiTableModel;
import org.onosproject.net.pi.model.PiTableType;
import org.slf4j.Logger;
import p4.config.v1.P4InfoOuterClass;
import p4.config.v1.P4InfoOuterClass.Action;
import p4.config.v1.P4InfoOuterClass.ActionProfile;
import p4.config.v1.P4InfoOuterClass.ActionRef;
import p4.config.v1.P4InfoOuterClass.ControllerPacketMetadata;
import p4.config.v1.P4InfoOuterClass.Counter;
import p4.config.v1.P4InfoOuterClass.CounterSpec;
import p4.config.v1.P4InfoOuterClass.DirectCounter;
import p4.config.v1.P4InfoOuterClass.DirectMeter;
import p4.config.v1.P4InfoOuterClass.MatchField;
import p4.config.v1.P4InfoOuterClass.Meter;
import p4.config.v1.P4InfoOuterClass.MeterSpec;
import p4.config.v1.P4InfoOuterClass.P4Info;
import p4.config.v1.P4InfoOuterClass.Table;
import p4.config.v1.P4Types;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static java.lang.String.format;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Parser of P4Info to PI pipeline model instances.
 */
public final class P4InfoParser {

    private static final Logger log = getLogger(P4InfoParser.class);

    private static final String PACKET_IN = "packet_in";
    private static final String PACKET_OUT = "packet_out";

    private static final Map<CounterSpec.Unit, PiCounterModel.Unit> COUNTER_UNIT_MAP =
            new ImmutableMap.Builder<CounterSpec.Unit, PiCounterModel.Unit>()
                    .put(CounterSpec.Unit.BYTES, PiCounterModel.Unit.BYTES)
                    .put(CounterSpec.Unit.PACKETS, PiCounterModel.Unit.PACKETS)
                    .put(CounterSpec.Unit.BOTH, PiCounterModel.Unit.PACKETS_AND_BYTES)
                    // Don't map UNSPECIFIED as we don't support it at the moment.
                    .build();

    private static final Map<MeterSpec.Unit, PiMeterModel.Unit> METER_UNIT_MAP =
            new ImmutableMap.Builder<MeterSpec.Unit, PiMeterModel.Unit>()
                    .put(MeterSpec.Unit.BYTES, PiMeterModel.Unit.BYTES)
                    .put(MeterSpec.Unit.PACKETS, PiMeterModel.Unit.PACKETS)
                    // Don't map UNSPECIFIED as we don't support it at the moment.
                    .build();

    private static final Map<String, PiPacketOperationType> PACKET_OPERATION_TYPE_MAP =
            new ImmutableMap.Builder<String, PiPacketOperationType>()
                    .put(PACKET_IN, PiPacketOperationType.PACKET_IN)
                    .put(PACKET_OUT, PiPacketOperationType.PACKET_OUT)
                    .build();

    private static final Map<MatchField.MatchType, PiMatchType> MATCH_TYPE_MAP =
            new ImmutableMap.Builder<MatchField.MatchType, PiMatchType>()
                    .put(MatchField.MatchType.EXACT, PiMatchType.EXACT)
                    .put(MatchField.MatchType.LPM, PiMatchType.LPM)
                    .put(MatchField.MatchType.TERNARY, PiMatchType.TERNARY)
                    .put(MatchField.MatchType.RANGE, PiMatchType.RANGE)
                    .put(MatchField.MatchType.OPTIONAL, PiMatchType.OPTIONAL)
                    // Don't map UNSPECIFIED as we don't support it at the moment.
                    .build();
    public static final int NO_SIZE = -1;

    private P4InfoParser() {
        // Utility class, hides constructor.
    }

    /**
     * Parse the given URL pointing to a P4Info file (in text format) to a PI pipeline model.
     *
     * @param p4InfoUrl URL to P4Info in text form
     * @return PI pipeline model
     * @throws P4InfoParserException if the P4Info file cannot be parsed (see message)
     */
    public static PiPipelineModel parse(URL p4InfoUrl) throws P4InfoParserException {

        final P4Info p4info;
        try {
            p4info = getP4InfoMessage(p4InfoUrl);
        } catch (IOException e) {
            throw new P4InfoParserException("Unable to parse protobuf " + p4InfoUrl.toString(), e);
        }

        // Generate fingerprint of the pipeline by hashing p4info file
        final int fingerprint;
        try {
            HashingInputStream hin = new HashingInputStream(Hashing.crc32(), p4InfoUrl.openStream());
            //noinspection StatementWithEmptyBody
            while (hin.read() != -1) {
                // Do nothing. Reading all input stream to update hash.
            }
            fingerprint = hin.hash().asInt();
        } catch (IOException e) {
            throw new P4InfoParserException("Unable to generate fingerprint " + p4InfoUrl.toString(), e);
        }

        // Start by parsing and mapping instances to to their integer P4Info IDs.
        // Convenient to build the table model at the end.

        // Counters.
        final Map<Integer, PiCounterModel> counterMap = Maps.newHashMap();
        counterMap.putAll(parseCounters(p4info));
        counterMap.putAll(parseDirectCounters(p4info));

        // Meters.
        final Map<Integer, PiMeterModel> meterMap = Maps.newHashMap();
        meterMap.putAll(parseMeters(p4info));
        meterMap.putAll(parseDirectMeters(p4info));

        // Registers.
        final Map<Integer, PiRegisterModel> registerMap = Maps.newHashMap();
        registerMap.putAll(parseRegisters(p4info));

        // Action profiles.
        final Map<Integer, PiActionProfileModel> actProfileMap = parseActionProfiles(p4info);

        // Actions.
        final Map<Integer, PiActionModel> actionMap = parseActions(p4info);

        // Controller packet metadatas.
        final Map<PiPacketOperationType, PiPacketOperationModel> pktOpMap = parseCtrlPktMetadatas(p4info);

        // Finally, parse tables.
        final ImmutableMap.Builder<PiTableId, PiTableModel> tableImmMapBuilder =
                ImmutableMap.builder();
        for (Table tableMsg : p4info.getTablesList()) {
            final PiTableId tableId = PiTableId.of(tableMsg.getPreamble().getName());
            // Parse match fields.
            final ImmutableMap.Builder<PiMatchFieldId, PiMatchFieldModel> tableFieldMapBuilder =
                    ImmutableMap.builder();
            for (MatchField fieldMsg : tableMsg.getMatchFieldsList()) {
                final PiMatchFieldId fieldId = PiMatchFieldId.of(fieldMsg.getName());
                tableFieldMapBuilder.put(
                        fieldId,
                        new P4MatchFieldModel(fieldId,
                                              isFieldString(p4info, fieldMsg.getTypeName().getName()) ?
                                                      P4MatchFieldModel.BIT_WIDTH_UNDEFINED :
                                                      fieldMsg.getBitwidth(),
                                              mapMatchFieldType(fieldMsg.getMatchType())));

            }
            // Retrieve action models by inter IDs.
            final ImmutableMap.Builder<PiActionId, PiActionModel> tableActionMapBuilder =
                    ImmutableMap.builder();
            tableMsg.getActionRefsList().stream()
                    .map(ActionRef::getId)
                    .map(actionMap::get)
                    .forEach(actionModel -> tableActionMapBuilder.put(actionModel.id(), actionModel));
            // Retrieve direct meters by integer IDs.
            final ImmutableMap.Builder<PiMeterId, PiMeterModel> tableMeterMapBuilder =
                    ImmutableMap.builder();
            tableMsg.getDirectResourceIdsList()
                    .stream()
                    .map(meterMap::get)
                    // Direct resource ID might be that of a counter.
                    // Filter out missed mapping.
                    .filter(Objects::nonNull)
                    .forEach(meterModel -> tableMeterMapBuilder.put(meterModel.id(), meterModel));
            // Retrieve direct counters by integer IDs.
            final ImmutableMap.Builder<PiCounterId, PiCounterModel> tableCounterMapBuilder =
                    ImmutableMap.builder();
            tableMsg.getDirectResourceIdsList()
                    .stream()
                    .map(counterMap::get)
                    // As before, resource ID might be that of a meter.
                    // Filter out missed mapping.
                    .filter(Objects::nonNull)
                    .forEach(counterModel -> tableCounterMapBuilder.put(counterModel.id(), counterModel));
            tableImmMapBuilder.put(
                    tableId,
                    new P4TableModel(
                            PiTableId.of(tableMsg.getPreamble().getName()),
                            tableMsg.getImplementationId() == 0 ? PiTableType.DIRECT : PiTableType.INDIRECT,
                            actProfileMap.get(tableMsg.getImplementationId()),
                            tableMsg.getSize(),
                            tableCounterMapBuilder.build(),
                            tableMeterMapBuilder.build(),
                            !tableMsg.getIdleTimeoutBehavior()
                                    .equals(Table.IdleTimeoutBehavior.NO_TIMEOUT),
                            tableFieldMapBuilder.build(),
                            tableActionMapBuilder.build(),
                            actionMap.get(tableMsg.getConstDefaultActionId()),
                            tableMsg.getIsConstTable()));

        }

        // Get a map with proper PI IDs for some of those maps we created at the beginning.
        ImmutableMap<PiCounterId, PiCounterModel> counterImmMap = ImmutableMap.copyOf(
                counterMap.values().stream()
                        .collect(Collectors.toMap(PiCounterModel::id, c -> c)));
        ImmutableMap<PiMeterId, PiMeterModel> meterImmMap = ImmutableMap.copyOf(
                meterMap.values().stream()
                        .collect(Collectors.toMap(PiMeterModel::id, m -> m)));
        ImmutableMap<PiRegisterId, PiRegisterModel> registerImmMap = ImmutableMap.copyOf(
                registerMap.values().stream()
                        .collect(Collectors.toMap(PiRegisterModel::id, r -> r)));
        ImmutableMap<PiActionProfileId, PiActionProfileModel> actProfileImmMap = ImmutableMap.copyOf(
                actProfileMap.values().stream()
                        .collect(Collectors.toMap(PiActionProfileModel::id, a -> a)));

        return new P4PipelineModel(
                tableImmMapBuilder.build(),
                counterImmMap,
                meterImmMap,
                registerImmMap,
                actProfileImmMap,
                ImmutableMap.copyOf(pktOpMap),
                fingerprint);
    }


    private static Map<Integer, PiCounterModel> parseCounters(P4Info p4info)
            throws P4InfoParserException {
        final Map<Integer, PiCounterModel> counterMap = Maps.newHashMap();
        for (Counter counterMsg : p4info.getCountersList()) {
            counterMap.put(
                    counterMsg.getPreamble().getId(),
                    new P4CounterModel(
                            PiCounterId.of(counterMsg.getPreamble().getName()),
                            PiCounterType.INDIRECT,
                            mapCounterSpecUnit(counterMsg.getSpec()),
                            null,
                            counterMsg.getSize()));
        }
        return counterMap;
    }

    private static Map<Integer, PiCounterModel> parseDirectCounters(P4Info p4info)
            throws P4InfoParserException {
        final Map<Integer, PiCounterModel> counterMap = Maps.newHashMap();
        for (DirectCounter dirCounterMsg : p4info.getDirectCountersList()) {
            counterMap.put(
                    dirCounterMsg.getPreamble().getId(),
                    new P4CounterModel(
                            PiCounterId.of(dirCounterMsg.getPreamble().getName()),
                            PiCounterType.DIRECT,
                            mapCounterSpecUnit(dirCounterMsg.getSpec()),
                            PiTableId.of(getTableName(dirCounterMsg.getDirectTableId(), p4info)),
                            NO_SIZE));
        }
        return counterMap;
    }

    private static Map<Integer, PiMeterModel> parseMeters(P4Info p4info)
            throws P4InfoParserException {
        final Map<Integer, PiMeterModel> meterMap = Maps.newHashMap();
        for (Meter meterMsg : p4info.getMetersList()) {
            meterMap.put(
                    meterMsg.getPreamble().getId(),
                    new P4MeterModel(
                            PiMeterId.of(meterMsg.getPreamble().getName()),
                            PiMeterType.INDIRECT,
                            mapMeterSpecUnit(meterMsg.getSpec()),
                            null,
                            meterMsg.getSize()));
        }
        return meterMap;
    }

    private static Map<Integer, PiMeterModel> parseDirectMeters(P4Info p4info)
            throws P4InfoParserException {
        final Map<Integer, PiMeterModel> meterMap = Maps.newHashMap();
        for (DirectMeter dirMeterMsg : p4info.getDirectMetersList()) {
            meterMap.put(
                    dirMeterMsg.getPreamble().getId(),
                    new P4MeterModel(
                            PiMeterId.of(dirMeterMsg.getPreamble().getName()),
                            PiMeterType.DIRECT,
                            mapMeterSpecUnit(dirMeterMsg.getSpec()),
                            PiTableId.of(getTableName(dirMeterMsg.getDirectTableId(), p4info)),
                            NO_SIZE));
        }
        return meterMap;
    }

    private static Map<Integer, PiRegisterModel> parseRegisters(P4Info p4info) {
        final Map<Integer, PiRegisterModel> registerMap = Maps.newHashMap();
        for (P4InfoOuterClass.Register registerMsg : p4info.getRegistersList()) {
            registerMap.put(registerMsg.getPreamble().getId(),
                            new P4RegisterModel(PiRegisterId.of(registerMsg.getPreamble().getName()),
                                                registerMsg.getSize()));
        }
        return registerMap;
    }

    private static Map<Integer, PiActionProfileModel> parseActionProfiles(P4Info p4info)
            throws P4InfoParserException {
        final Map<Integer, PiActionProfileModel> actProfileMap = Maps.newHashMap();
        for (ActionProfile actProfileMsg : p4info.getActionProfilesList()) {
            final ImmutableSet.Builder<PiTableId> tableIdSetBuilder = ImmutableSet.builder();
            for (int tableId : actProfileMsg.getTableIdsList()) {
                tableIdSetBuilder.add(PiTableId.of(getTableName(tableId, p4info)));
            }
            // TODO: we should copy all annotations to model classes for later
            //  use in the PI framework.
            // This is a temporary workaround to the inability of p4c to
            // correctly interpret P4Runtime-defined max_group_size annotation:
            // https://s3-us-west-2.amazonaws.com/p4runtime/docs/master/
            // P4Runtime-Spec.html#sec-p4info-action-profile
            final String maxSizeAnnString = findAnnotation(
                    "max_group_size", actProfileMsg.getPreamble());
            final int maxSizeAnn = maxSizeAnnString != null
                    ? Integer.valueOf(maxSizeAnnString) : 0;
            final int maxGroupSize;
            if (actProfileMsg.getMaxGroupSize() == 0 && maxSizeAnn != 0) {
                log.warn("Found valid 'max_group_size' annotation for " +
                                 "ActionProfile {}, using that...",
                         actProfileMsg.getPreamble().getName());
                maxGroupSize = maxSizeAnn;
            } else {
                maxGroupSize = actProfileMsg.getMaxGroupSize();
            }

            actProfileMap.put(
                    actProfileMsg.getPreamble().getId(),
                    new P4ActionProfileModel(
                            PiActionProfileId.of(actProfileMsg.getPreamble().getName()),
                            tableIdSetBuilder.build(),
                            actProfileMsg.getWithSelector(),
                            actProfileMsg.getSize(),
                            maxGroupSize));
        }
        return actProfileMap;
    }

    private static Map<Integer, PiActionModel> parseActions(P4Info p4info) {
        final Map<Integer, PiActionModel> actionMap = Maps.newHashMap();
        for (Action actionMsg : p4info.getActionsList()) {
            final ImmutableMap.Builder<PiActionParamId, PiActionParamModel> paramMapBuilder =
                    ImmutableMap.builder();
            actionMsg.getParamsList().forEach(paramMsg -> {
                final PiActionParamId paramId = PiActionParamId.of(paramMsg.getName());
                paramMapBuilder.put(paramId,
                                    new P4ActionParamModel(
                                            PiActionParamId.of(paramMsg.getName()),
                                            isFieldString(p4info, paramMsg.getTypeName().getName()) ?
                                                    P4ActionParamModel.BIT_WIDTH_UNDEFINED :
                                                    paramMsg.getBitwidth()));
            });
            actionMap.put(
                    actionMsg.getPreamble().getId(),
                    new P4ActionModel(
                            PiActionId.of(actionMsg.getPreamble().getName()),
                            paramMapBuilder.build()));

        }
        return actionMap;
    }

    private static Map<PiPacketOperationType, PiPacketOperationModel> parseCtrlPktMetadatas(P4Info p4info)
            throws P4InfoParserException {
        final Map<PiPacketOperationType, PiPacketOperationModel> packetOpMap = Maps.newHashMap();
        for (ControllerPacketMetadata ctrlPktMetaMsg : p4info.getControllerPacketMetadataList()) {
            final ImmutableList.Builder<PiPacketMetadataModel> metadataListBuilder =
                    ImmutableList.builder();
            ctrlPktMetaMsg.getMetadataList().forEach(metadataMsg -> metadataListBuilder.add(
                    new P4PacketMetadataModel(PiPacketMetadataId.of(metadataMsg.getName()),
                                              isFieldString(p4info, metadataMsg.getTypeName().getName()) ?
                                                      P4PacketMetadataModel.BIT_WIDTH_UNDEFINED :
                                                      metadataMsg.getBitwidth())));
            packetOpMap.put(
                    mapPacketOpType(ctrlPktMetaMsg.getPreamble().getName()),
                    new P4PacketOperationModel(mapPacketOpType(ctrlPktMetaMsg.getPreamble().getName()),
                                               metadataListBuilder.build()));

        }
        return packetOpMap;
    }

    private static P4Info getP4InfoMessage(URL p4InfoUrl) throws IOException {
        InputStream p4InfoStream = p4InfoUrl.openStream();
        P4Info.Builder p4InfoBuilder = P4Info.newBuilder();
        TextFormat.getParser().merge(new InputStreamReader(p4InfoStream),
                                     ExtensionRegistry.getEmptyRegistry(),
                                     p4InfoBuilder);
        return p4InfoBuilder.build();
    }

    private static String getTableName(int id, P4Info p4info)
            throws P4InfoParserException {
        return p4info.getTablesList().stream()
                .filter(t -> t.getPreamble().getId() == id)
                .findFirst()
                .orElseThrow(() -> new P4InfoParserException(format(
                        "Not such table with ID %d", id)))
                .getPreamble()
                .getName();
    }

    private static PiCounterModel.Unit mapCounterSpecUnit(CounterSpec spec)
            throws P4InfoParserException {
        if (!COUNTER_UNIT_MAP.containsKey(spec.getUnit())) {
            throw new P4InfoParserException(format(
                    "Unrecognized counter unit '%s'", spec.getUnit()));
        }
        return COUNTER_UNIT_MAP.get(spec.getUnit());
    }

    private static PiMeterModel.Unit mapMeterSpecUnit(MeterSpec spec)
            throws P4InfoParserException {
        if (!METER_UNIT_MAP.containsKey(spec.getUnit())) {
            throw new P4InfoParserException(format(
                    "Unrecognized meter unit '%s'", spec.getUnit()));
        }
        return METER_UNIT_MAP.get(spec.getUnit());
    }

    private static PiPacketOperationType mapPacketOpType(String name)
            throws P4InfoParserException {
        if (!PACKET_OPERATION_TYPE_MAP.containsKey(name)) {
            throw new P4InfoParserException(format(
                    "Unrecognized controller packet metadata name '%s'", name));
        }
        return PACKET_OPERATION_TYPE_MAP.get(name);
    }

    private static PiMatchType mapMatchFieldType(MatchField.MatchType type)
            throws P4InfoParserException {
        if (!MATCH_TYPE_MAP.containsKey(type)) {
            throw new P4InfoParserException(format(
                    "Unrecognized match field type '%s'", type));
        }
        return MATCH_TYPE_MAP.get(type);
    }

    private static String findAnnotation(String name, P4InfoOuterClass.Preamble preamble) {
        return preamble.getAnnotationsList().stream()
                .filter(a -> a.startsWith("@" + name))
                // e.g. @my_annotaion(value)
                .map(a -> a.substring(name.length() + 2, a.length() - 1))
                .findFirst()
                .orElse(null);
    }

    private static boolean isFieldString(P4Info p4info, String fieldTypeName) {
        P4Types.P4TypeInfo p4TypeInfo = p4info.getTypeInfo();
        return p4TypeInfo.containsNewTypes(fieldTypeName) &&
                p4TypeInfo.getNewTypesOrThrow(fieldTypeName).hasTranslatedType() &&
                p4TypeInfo.getNewTypesOrThrow(fieldTypeName).getTranslatedType().hasSdnString();
    }
}
