/*
 * 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 org.onosproject.net.pi.model.PiMeterId;
import org.onosproject.net.pi.model.PiMeterType;
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.model.PiTableId;
import org.onosproject.net.pi.runtime.PiMeterBand;
import org.onosproject.net.pi.runtime.PiMeterCellConfig;
import org.onosproject.net.pi.runtime.PiMeterCellId;
import org.onosproject.net.pi.runtime.PiTableEntry;
import org.slf4j.Logger;
import p4.v1.P4RuntimeOuterClass;
import p4.v1.P4RuntimeOuterClass.DirectMeterEntry;
import p4.v1.P4RuntimeOuterClass.Entity;
import p4.v1.P4RuntimeOuterClass.MeterConfig;
import p4.v1.P4RuntimeOuterClass.MeterEntry;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static java.lang.String.format;
import static org.onosproject.p4runtime.ctl.P4RuntimeUtils.indexMsg;
import static org.slf4j.LoggerFactory.getLogger;
import static p4.v1.P4RuntimeOuterClass.Entity.EntityCase.DIRECT_METER_ENTRY;
import static p4.v1.P4RuntimeOuterClass.Entity.EntityCase.METER_ENTRY;

/**
 * Encoder/decoder of PI meter cell configurations to meter entry protobuf
 * messages, and vice versa.
 */
final class MeterEntryCodec {

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

    private MeterEntryCodec() {
        // Hides constructor.
    }

    /**
     * Returns a collection of P4Runtime entity protobuf messages describing
     * both meter or direct meter entries, encoded from the given collection of
     * PI meter cell configurations, for the given pipeconf. If a PI meter cell
     * configurations cannot be encoded, it is skipped, hence the returned
     * collection might have different size than the input one.
     *
     * @param cellConfigs meter cell configurations
     * @param pipeconf    pipeconf
     * @return collection of entity messages describing both meter or direct
     * meter entries
     */
    static List<Entity> encodePiMeterCellConfigs(List<PiMeterCellConfig> cellConfigs,
                                                       PiPipeconf pipeconf) {
        final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);

        if (browser == null) {
            log.error("Unable to get a P4Info browser for pipeconf {}", pipeconf.id());
            return Collections.emptyList();
        }

        return cellConfigs
                .stream()
                .map(cellConfig -> {
                    try {
                        return encodePiMeterCellConfig(cellConfig, pipeconf, browser);
                    } catch (P4InfoBrowser.NotFoundException | CodecException e) {
                        log.warn("Unable to encode PI meter cell id: {}", e.getMessage());
                        log.debug("exception", e);
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    /**
     * Returns a collection of P4Runtime entity protobuf messages to be used in
     * requests to read all cells from the given meter identifiers. Works for
     * both indirect or direct meters. If a PI meter identifier cannot be
     * encoded, it is skipped, hence the returned collection might have
     * different size than the input one.
     *
     * @param meterIds meter identifiers
     * @param pipeconf pipeconf
     * @return collection of entity messages
     */
    static List<Entity> readAllCellsEntities(List<PiMeterId> meterIds,
                                                   PiPipeconf pipeconf) {
        final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);

        if (browser == null) {
            log.error("Unable to get a P4Info browser for pipeconf {}", pipeconf.id());
            return Collections.emptyList();
        }

        return meterIds
                .stream()
                .map(meterId -> {
                    try {
                        return readAllCellsEntity(meterId, pipeconf, browser);
                    } catch (P4InfoBrowser.NotFoundException | CodecException e) {
                        log.warn("Unable to encode meter ID to read-all-cells entity: {}",
                                 e.getMessage());
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    /**
     * Returns a collection of PI meter cell configurations, decoded from the
     * given P4Runtime entity protobuf messages describing both meter or direct
     * meter entries, and pipeconf. If an entity message cannot be encoded, it
     * is skipped, hence the returned collection might have different size than
     * the input one.
     *
     * @param entities P4Runtime entity messages
     * @param pipeconf pipeconf
     * @return collection of PI meter cell data
     */
    static List<PiMeterCellConfig> decodeMeterEntities(List<Entity> entities,
                                                       PiPipeconf pipeconf) {
        final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);

        if (browser == null) {
            log.error("Unable to get a P4Info browser for pipeconf {}", pipeconf.id());
            return Collections.emptyList();
        }

        return entities
                .stream()
                .filter(entity -> entity.getEntityCase() == METER_ENTRY ||
                        entity.getEntityCase() == DIRECT_METER_ENTRY)
                .map(entity -> {
                    try {
                        return decodeMeterEntity(entity, pipeconf, browser);
                    } catch (CodecException | P4InfoBrowser.NotFoundException e) {
                        log.warn("Unable to decode meter entity message: {}", e.getMessage());
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    private static Entity encodePiMeterCellConfig(PiMeterCellConfig config,
                                                  PiPipeconf pipeconf,
                                                  P4InfoBrowser browser)
            throws P4InfoBrowser.NotFoundException, CodecException {

        int meterId;
        Entity entity;
        MeterConfig meterConfig;

        PiMeterBand[] bands = config.meterBands()
                .toArray(new PiMeterBand[config.meterBands().size()]);
        if (bands.length == 2) {
            long cir, cburst, pir, pburst;
            // The band with bigger burst is peak if rate of them is equal.
            if (bands[0].rate() > bands[1].rate() ||
                    (bands[0].rate() == bands[1].rate() &&
                            bands[0].burst() >= bands[1].burst())) {
                cir = bands[1].rate();
                cburst = bands[1].burst();
                pir = bands[0].rate();
                pburst = bands[0].burst();
            } else {
                cir = bands[0].rate();
                cburst = bands[0].burst();
                pir = bands[1].rate();
                pburst = bands[1].burst();
            }
            meterConfig = MeterConfig.newBuilder()
                    .setCir(cir)
                    .setCburst(cburst)
                    .setPir(pir)
                    .setPburst(pburst)
                    .build();
        } else if (bands.length == 0) {
            // When reading meter cells.
            meterConfig = null;
        } else {
            throw new CodecException("number of meter bands should be either 2 or 0");
        }

        switch (config.cellId().meterType()) {
            case INDIRECT:
                meterId = browser.meters()
                        .getByName(config.cellId().meterId().id())
                        .getPreamble().getId();
                MeterEntry.Builder indEntryBuilder = MeterEntry.newBuilder()
                        .setMeterId(meterId)
                        .setIndex(indexMsg(config.cellId().index()));
                if (meterConfig != null) {
                    indEntryBuilder.setConfig(meterConfig);
                }
                entity = Entity.newBuilder()
                        .setMeterEntry(indEntryBuilder.build()).build();
                break;
            case DIRECT:
                DirectMeterEntry.Builder dirEntryBuilder = DirectMeterEntry.newBuilder()
                        .setTableEntry(TableEntryEncoder.encode(
                                config.cellId().tableEntry(), pipeconf));
                if (meterConfig != null) {
                    dirEntryBuilder.setConfig(meterConfig);
                }
                entity = Entity.newBuilder()
                        .setDirectMeterEntry(dirEntryBuilder.build()).build();
                break;
            default:
                throw new CodecException(format("unrecognized PI meter type '%s'",
                                                config.cellId().meterType()));
        }

        return entity;
    }

    private static Entity readAllCellsEntity(PiMeterId meterId,
                                             PiPipeconf pipeconf,
                                             P4InfoBrowser browser)
            throws P4InfoBrowser.NotFoundException, CodecException {

        if (!pipeconf.pipelineModel().meter(meterId).isPresent()) {
            throw new CodecException(format(
                    "not such meter '%s' in pipeline model", meterId));
        }
        final PiMeterType meterType = pipeconf.pipelineModel()
                .meter(meterId).get().meterType();

        switch (meterType) {
            case INDIRECT:
                final int p4InfoMeterId = browser.meters()
                        .getByName(meterId.id())
                        .getPreamble().getId();
                return Entity.newBuilder().setMeterEntry(
                        P4RuntimeOuterClass.MeterEntry.newBuilder()
                                // Index unset to read all cells
                                .setMeterId(p4InfoMeterId)
                                .build())
                        .build();
            case DIRECT:
                final PiTableId tableId = pipeconf.pipelineModel()
                        .meter(meterId).get().table();
                if (tableId == null) {
                    throw new CodecException(format(
                            "null table for direct meter '%s'", meterId));
                }
                final int p4TableId = browser.tables().getByName(tableId.id())
                        .getPreamble().getId();
                return Entity.newBuilder().setDirectMeterEntry(
                        P4RuntimeOuterClass.DirectMeterEntry.newBuilder()
                                .setTableEntry(
                                        // Match unset to read all cells
                                        P4RuntimeOuterClass.TableEntry.newBuilder()
                                                .setTableId(p4TableId)
                                                .build())
                                .build())
                        .build();
            default:
                throw new CodecException(format(
                        "unrecognized PI meter type '%s'", meterType));
        }
    }

    private static PiMeterCellConfig decodeMeterEntity(Entity entity,
                                                       PiPipeconf pipeconf,
                                                       P4InfoBrowser browser)
            throws CodecException, P4InfoBrowser.NotFoundException {

        MeterConfig meterConfig;
        PiMeterCellId piCellId;

        if (entity.getEntityCase() == METER_ENTRY) {
            String meterName = browser.meters()
                    .getById(entity.getMeterEntry().getMeterId())
                    .getPreamble()
                    .getName();
            piCellId = PiMeterCellId.ofIndirect(
                    PiMeterId.of(meterName),
                    entity.getMeterEntry().getIndex().getIndex());
            meterConfig = entity.getMeterEntry().getConfig();
        } else if (entity.getEntityCase() == DIRECT_METER_ENTRY) {
            PiTableEntry piTableEntry = TableEntryEncoder.decode(
                    entity.getDirectMeterEntry().getTableEntry(),
                    pipeconf);
            piCellId = PiMeterCellId.ofDirect(piTableEntry);
            meterConfig = entity.getDirectMeterEntry().getConfig();
        } else {
            throw new CodecException(format(
                    "unrecognized entity type '%s' in P4Runtime message",
                    entity.getEntityCase().name()));
        }

        return PiMeterCellConfig.builder()
                .withMeterCellId(piCellId)
                .withMeterBand(new PiMeterBand(meterConfig.getCir(),
                                               meterConfig.getCburst()))
                .withMeterBand(new PiMeterBand(meterConfig.getPir(),
                                               meterConfig.getPburst()))
                .build();
    }
}
