/*
 * 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 IllegalStateException("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 IllegalStateException(String.format("Group bucket contains no output instruction. GroupId=%s",
                                                     groupId));
        }
        if (outputInstructions.size() != 1) {
            throw new IllegalStateException(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 IllegalStateException(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);
        }
    }
}