/*
 * 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.drivers.bmv2.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Sets;
import org.onosproject.core.GroupId;
import org.onosproject.drivers.bmv2.api.runtime.Bmv2PreGroup;
import org.onosproject.drivers.bmv2.api.runtime.Bmv2PreJsonGroups;
import org.onosproject.drivers.bmv2.api.runtime.Bmv2PreNode;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.group.Group;
import org.onosproject.net.group.GroupDescription;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * Implementation of BMv2 PRE group translation logic.
 */
public final class Bmv2PreGroupTranslatorImpl {

    private static final int BMV2_PORT_MAP_SIZE = 256;

    //hidden constructor
    private Bmv2PreGroupTranslatorImpl() {
    }

    /**
     * Returns a BMv2 PRE group equivalent to given group.
     *
     * @param group group
     * @return a BMv2 PRE group
     */
    public static Bmv2PreGroup translate(Group group) {
        if (!group.type().equals(GroupDescription.Type.ALL)) {
            throw new RuntimeException("Unable to translate the group to BMv2 PRE group." +
                                               "A BMv2 PRE group is to be of ALL type. GroupId="
                                               + group.id());
        }

        Bmv2PreGroup.Bmv2PreGroupBuilder bmv2PreGroupBuilder = Bmv2PreGroup.builder();
        bmv2PreGroupBuilder.withGroupId(group.id().id());
        // RID is generated per an MG since L2 broadcast can be considered as a MG that have a single RID.
        // for simplicity RID will be assigned to zero for any node in an MG.
        int replicationId = 0;

        Set<PortNumber> outPorts = Sets.newHashSet();
        group.buckets().buckets().forEach(groupBucket -> {
            //get output instructions of the bucket
            Set<Instructions.OutputInstruction> outputInstructions = getOutputInstructions(groupBucket.treatment());
            //check validity of output instructions
            checkOutputInstructions(group.id(), outputInstructions);
            outPorts.add(outputInstructions.iterator().next().port());
        });
        validatePorts(outPorts);
        bmv2PreGroupBuilder.addNode(Bmv2PreNode.builder()
                                            .withRid(replicationId)
                                            .withPortMap(buildPortMap(outPorts))
                                            .build());
        return bmv2PreGroupBuilder.build();
    }

    /**
     * Converts a PRE group list in JSON notation to list of Bmv2PreGroups.
     *
     * @param groupListJson group list string ing JSON notation
     * @return list of Bmv2PreGroups
     * @throws IOException in case JSON string can not be parsed
     */
    public static List<Bmv2PreGroup> translate(String groupListJson) throws IOException {
        List<Bmv2PreGroup> preGroups = new ArrayList<>();
        if (groupListJson == null) {
            return preGroups;
        }
        ObjectMapper mapper = new ObjectMapper();
        Bmv2PreJsonGroups bmv2PreJsonGroups = mapper.readValue(groupListJson, Bmv2PreJsonGroups.class);

        Bmv2PreGroup.Bmv2PreGroupBuilder bmv2PreGroupBuilder;
        for (Bmv2PreJsonGroups.Mgrp mgrp : bmv2PreJsonGroups.mgrps) {

            bmv2PreGroupBuilder = Bmv2PreGroup.builder();
            bmv2PreGroupBuilder.withGroupId(mgrp.id);

            for (int l1handleId : mgrp.l1handles) {
                Bmv2PreJsonGroups.L1Handle l1handle = getL1Handle(l1handleId, bmv2PreJsonGroups.l1handles);
                if (l1handle == null) {
                    continue;
                }
                Bmv2PreJsonGroups.L2Handle l2handle = getL2Handle(l1handle.l2handle, bmv2PreJsonGroups.l2handles);
                if (l2handle == null) {
                    continue;
                }
                bmv2PreGroupBuilder.addNode(Bmv2PreNode.builder()
                                                    .withRid(l1handle.rid)
                                                    .withPortMap(buildPortMap(l2handle.ports))
                                                    .withL1Handle(l1handleId)
                                                    .build());
            }
            preGroups.add(bmv2PreGroupBuilder.build());
        }
        return preGroups;
    }

    /**
     * Retrieves L1Handle object pointed by given L1 handle pointer from L1 handles list.
     *
     * @param l1handlePointer pointer to a L1 handle
     * @param l1handles       list of L1 handles
     * @return L1 handle object if exists; null otherwise
     */
    private static Bmv2PreJsonGroups.L1Handle getL1Handle(int l1handlePointer,
                                                          Bmv2PreJsonGroups.L1Handle[] l1handles) {
        for (Bmv2PreJsonGroups.L1Handle l1Handle : l1handles) {
            if (l1handlePointer == l1Handle.handle) {
                return l1Handle;
            }
        }
        return null;
    }

    /**
     * Retrieves L2Handle object pointed by given L2 handle pointer from L2 handles list.
     *
     * @param l2handlePointer pointer to a L2 handle
     * @param l2handles       list of L2 handles
     * @return L2 handle object if exists; null otherwise
     */
    private static Bmv2PreJsonGroups.L2Handle getL2Handle(int l2handlePointer,
                                                          Bmv2PreJsonGroups.L2Handle[] l2handles) {
        for (Bmv2PreJsonGroups.L2Handle l2handle : l2handles) {
            if (l2handlePointer == l2handle.handle) {
                return l2handle;
            }
        }
        return null;
    }

    /**
     * Builds a port map string composing of 1 and 0s.
     * BMv2 API reads a port map from most significant to least significant char.
     * Index of 1s indicates port numbers.
     * For example, if port numbers are 4,3 and 1, the generated port map string looks like 11010.
     *
     * @param outPorts set of output port numbers
     * @return port map string
     */
    private static String buildPortMap(Set<PortNumber> outPorts) {
        //Sorts port numbers in descending order
        SortedSet<PortNumber> outPortsSorted = new TreeSet<>((o1, o2) -> (int) (o2.toLong() - o1.toLong()));
        outPortsSorted.addAll(outPorts);
        PortNumber biggestPort = outPortsSorted.iterator().next();
        int portMapSize = (int) biggestPort.toLong() + 1;
        //init and fill port map with zero characters
        char[] portMap = new char[portMapSize];
        Arrays.fill(portMap, '0');
        //fill in the ports with 1
        outPortsSorted.forEach(portNumber -> portMap[portMapSize - (int) portNumber.toLong() - 1] = '1');
        return String.valueOf(portMap);
    }

    /**
     * Builds a port map string composing of 1 and 0s.
     * BMv2 API reads a port map from most significant to least significant char.
     * The index of 1s indicates port numbers.
     * For example, if port numbers are 4,3 and 1, the generated port map string looks like 11010.
     *
     * @param portArr array of output port numbers
     * @return port map string
     */
    private static String buildPortMap(int[] portArr) {
        Set<PortNumber> outPorts = new HashSet<>();
        for (int port : portArr) {
            outPorts.add(PortNumber.portNumber(port));
        }
        return buildPortMap(outPorts);
    }

    /**
     * Retrieves output instructions out of the instruction set of the given traffic treatment.
     *
     * @param trafficTreatment
     * @return set of output instructions
     */
    private static Set<Instructions.OutputInstruction> getOutputInstructions(TrafficTreatment trafficTreatment) {
        if (trafficTreatment == null ||
                trafficTreatment.allInstructions() == null) {
            return Sets.newHashSet();
        }
        Set<Instructions.OutputInstruction> resultList = Sets.newHashSet();
        trafficTreatment.allInstructions().forEach(instruction -> {
            if (instruction instanceof Instructions.OutputInstruction) {
                resultList.add((Instructions.OutputInstruction) instruction);
            }
        });
        return resultList;
    }

    /**
     * Checks validity of output instructions of a bucket.
     * A bucket of a an ALL group must only have one output instruction.
     * Other conditions can not pass the validation.
     *
     * @param groupId            group identifier
     * @param outputInstructions set of output instructions
     * @throws RuntimeException if the instructions can not be validated
     */
    private static void checkOutputInstructions(GroupId groupId,
                                                Set<Instructions.OutputInstruction> outputInstructions) {
        if (outputInstructions.isEmpty()) {
            throw new RuntimeException(String.format("Group bucket contains no output instruction. GroupId=%s",
                                                     groupId));
        }
        if (outputInstructions.size() != 1) {
            throw new RuntimeException(String.format("Group bucket contains more than one output instructions. " +
                                                             "Only one is supported. GroupId=%s", groupId));
        }
    }

    /**
     * Checks whether a port number is a valid physical BMv2 port or not.
     * If not, throws RuntimeException; does nothing otherwise.
     *
     * @param portNumber port number
     * @throws RuntimeException iff the port number can not be validated
     */
    private static void validatePort(PortNumber portNumber) {
        if (portNumber.toLong() < 0 || portNumber.toLong() >= BMV2_PORT_MAP_SIZE) {
            throw new RuntimeException(String.format("Port number %d is not a valid BMv2 physical port number." +
                                                             "Valid port range is [0,255]", portNumber));
        }
    }

    /**
     * Checks whether a port number is a valid physical BMv2 port or not.
     * If not, throws RuntimeException; does nothing otherwise.
     *
     * @param portNumbers port number set
     * @throws RuntimeException iff a port number can not be validated
     */
    private static void validatePorts(Set<PortNumber> portNumbers) {
        //validate one by one
        for (PortNumber portNumber : portNumbers) {
            validatePort(portNumber);
        }
    }
}