/*
 * Copyright 2018-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.net.pi.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.onosproject.net.Device;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
import org.onosproject.net.flow.instructions.Instructions.TruncateInstruction;
import org.onosproject.net.group.Group;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.model.PiPipelineInterpreter;
import org.onosproject.net.pi.runtime.PiCloneSessionEntry;
import org.onosproject.net.pi.runtime.PiMulticastGroupEntry;
import org.onosproject.net.pi.runtime.PiPreEntry;
import org.onosproject.net.pi.runtime.PiPreReplica;
import org.onosproject.net.pi.service.PiTranslationException;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.String.format;

/**
 * Implementation of replication group translation logic.
 */
final class PiReplicationGroupTranslatorImpl {

    private PiReplicationGroupTranslatorImpl() {
        // Hides constructor.
    }

    /**
     * Returns a PI PRE entry equivalent to the given group, for the given
     * pipeconf and device.
     * <p>
     * The passed group is expected to have type {@link GroupDescription.Type#ALL}
     * or {@link GroupDescription.Type#CLONE}.
     *
     * @param group    group
     * @param pipeconf pipeconf
     * @param device   device
     * @return PI PRE entry
     * @throws PiTranslationException if the group cannot be translated
     */
    static PiPreEntry translate(Group group, PiPipeconf pipeconf, Device device)
            throws PiTranslationException {

        checkNotNull(group);

        final List<OutputInstruction> outInstructions = Lists.newArrayList();
        int truncateMaxLen = PiCloneSessionEntry.DO_NOT_TRUNCATE;
        for (GroupBucket bucket : group.buckets().buckets()) {
            int numInstructionsInBucket = bucket.treatment().allInstructions().size();
            List<OutputInstruction> outputs =
                    getInstructions(bucket, Instruction.Type.OUTPUT, OutputInstruction.class);
            List<TruncateInstruction> truncates =
                    getInstructions(bucket, Instruction.Type.TRUNCATE, TruncateInstruction.class);
            if (outputs.size() != 1) {
                throw new PiTranslationException(
                        "support only groups with just one OUTPUT instruction per bucket");
            }
            outInstructions.add(outputs.get(0));
            if (truncates.size() != 0) {
                if (group.type() != GroupDescription.Type.CLONE) {
                    throw new PiTranslationException("only CLONE group support truncate instruction");
                }
                if (truncates.size() != 1) {
                    throw new PiTranslationException(
                            "support only groups with just one TRUNCATE instruction per bucket");
                }
                int truncateInstMaxLen = truncates.get(0).maxLen();
                if (truncateMaxLen != PiCloneSessionEntry.DO_NOT_TRUNCATE &&
                        truncateMaxLen != truncateInstMaxLen) {
                    throw new PiTranslationException("all TRUNCATE instruction must be the same in a CLONE group");
                }
                truncateMaxLen = truncateInstMaxLen;
            } else if (truncateMaxLen != PiCloneSessionEntry.DO_NOT_TRUNCATE) {
                // No truncate instruction found in this bucket, but previous bucket contains one.
                throw new PiTranslationException("all TRUNCATE instruction must be the same in a CLONE group");
            }
            if (numInstructionsInBucket != outputs.size() + truncates.size()) {
                throw new PiTranslationException("bucket contains unsupported instruction(s)");
            }
        }

        switch (group.type()) {
            case ALL:
                return PiMulticastGroupEntry.builder()
                        .withGroupId(group.id().id())
                        .addReplicas(getReplicas(outInstructions, device))
                        .build();
            case CLONE:
                return PiCloneSessionEntry.builder()
                        .withSessionId(group.id().id())
                        .addReplicas(getReplicas(outInstructions, device))
                        .withMaxPacketLengthBytes(truncateMaxLen)
                        .build();
            default:
                throw new PiTranslationException(format(
                        "group type %s not supported", group.type()));
        }
    }

    private static Set<PiPreReplica> getReplicas(
            Collection<OutputInstruction> instructions, Device device)
            throws PiTranslationException {
        // Account for multiple replicas for the same port.
        final Map<PortNumber, Set<PiPreReplica>> replicaMap = Maps.newHashMap();
        final List<PortNumber> ports = instructions.stream()
                .map(OutputInstruction::port)
                .collect(Collectors.toList());
        for (PortNumber port : ports) {
            if (port.isLogical()) {
                port = logicalToPipelineSpecific(port, device);
            }
            // Use incremental instance IDs for replicas of the same port.
            replicaMap.putIfAbsent(port, Sets.newHashSet());
            replicaMap.get(port).add(
                    new PiPreReplica(port, replicaMap.get(port).size()));
        }
        return replicaMap.values().stream()
                .flatMap(Collection::stream)
                .collect(Collectors.toSet());
    }

    private static PortNumber logicalToPipelineSpecific(
            PortNumber logicalPort, Device device)
            throws PiTranslationException {
        if (!device.is(PiPipelineInterpreter.class)) {
            throw new PiTranslationException(
                    "missing interpreter, cannot map logical port " + logicalPort.toString());
        }
        final PiPipelineInterpreter interpreter = device.as(PiPipelineInterpreter.class);
        Optional<Integer> mappedPort = interpreter.mapLogicalPortNumber(logicalPort);
        if (!mappedPort.isPresent()) {
            throw new PiTranslationException(
                    "interpreter cannot map logical port " + logicalPort.toString());
        }
        return PortNumber.portNumber(mappedPort.get());
    }

    private static <I extends Instruction> List<I> getInstructions(GroupBucket bucket,
                                                                   Instruction.Type type,
                                                                   Class<I> instructionClass) {
        return bucket.treatment().allInstructions().stream()
                .filter(i -> i.type() == type)
                .map(instructionClass::cast)
                .collect(Collectors.toList());
    }
}
