/*
 * 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 com.google.common.collect.Maps;
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.runtime.PiActionGroup;
import org.onosproject.net.pi.runtime.PiActionGroupId;
import org.onosproject.net.pi.runtime.PiActionProfileId;
import p4.P4RuntimeOuterClass.ActionProfileGroup;
import p4.P4RuntimeOuterClass.ActionProfileGroup.Member;
import p4.P4RuntimeOuterClass.ActionProfileMember;
import p4.config.P4InfoOuterClass;

import java.util.Collection;
import java.util.Map;

import static java.lang.String.format;

/**
 * Encoder/Decoder for action profile group.
 */
public final class ActionProfileGroupEncoder {
    private ActionProfileGroupEncoder() {
        // hide default constructor
    }

    /**
     * Encode a PI action group to a action profile group.
     *
     * @param piActionGroup the action profile group
     * @param pipeconf the pipeconf
     * @return a action profile group encoded from PI action group
     * @throws P4InfoBrowser.NotFoundException if can't find action profile from P4Info browser
     * @throws EncodeException if can't find P4Info from pipeconf
     */
    static ActionProfileGroup encode(PiActionGroup piActionGroup, PiPipeconf pipeconf)
            throws P4InfoBrowser.NotFoundException, EncodeException {
        P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);

        if (browser == null) {
            throw new EncodeException(format("Can't get P4 info browser from pipeconf %s", pipeconf));
        }

        PiActionProfileId piActionProfileId = piActionGroup.actionProfileId();
        P4InfoOuterClass.ActionProfile actionProfile = browser.actionProfiles()
                .getByName(piActionProfileId.id());
        int actionProfileId = actionProfile.getPreamble().getId();
        ActionProfileGroup.Builder actionProfileGroupBuilder = ActionProfileGroup.newBuilder()
                        .setGroupId(piActionGroup.id().id())
                        .setActionProfileId(actionProfileId);

        switch (piActionGroup.type()) {
            case SELECT:
                actionProfileGroupBuilder.setType(ActionProfileGroup.Type.SELECT);
                break;
            default:
                throw new EncodeException(format("PI action group type %s not supported", piActionGroup.type()));
        }

        piActionGroup.members().forEach(m -> {
            // TODO: currently we don't set "watch" field of member
            Member member = Member.newBuilder()
                    .setMemberId(m.id().id())
                    .setWeight(m.weight())
                    .build();
            actionProfileGroupBuilder.addMembers(member);
        });

        actionProfileGroupBuilder.setMaxSize(piActionGroup.members().size());

        return actionProfileGroupBuilder.build();
    }

    /**
     * Decode an action profile group with members information to a PI action group.
     *
     * @param actionProfileGroup the action profile group
     * @param members members of the action profile group
     * @param pipeconf the pipeconf
     * @return decoded PI action group
     * @throws P4InfoBrowser.NotFoundException if can't find action profile from P4Info browser
     * @throws EncodeException if can't find P4Info from pipeconf
     */
    static PiActionGroup decode(ActionProfileGroup actionProfileGroup,
                                Collection<ActionProfileMember> members,
                                PiPipeconf pipeconf)
            throws P4InfoBrowser.NotFoundException, EncodeException {
        P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
        if (browser == null) {
            throw new EncodeException(format("Can't get P4 info browser from pipeconf %s", pipeconf));
        }
        PiActionGroup.Builder piActionGroupBuilder = PiActionGroup.builder();

        P4InfoOuterClass.ActionProfile actionProfile = browser.actionProfiles()
                .getById(actionProfileGroup.getActionProfileId());
        PiActionProfileId piActionProfileId = PiActionProfileId.of(actionProfile.getPreamble().getName());

        piActionGroupBuilder
                .withActionProfileId(piActionProfileId)
                .withId(PiActionGroupId.of(actionProfileGroup.getGroupId()));

        switch (actionProfileGroup.getType()) {
            case UNSPECIFIED:
                // FIXME: PI returns unspecified for select groups. Remove this case when PI bug will be fixed.
            case SELECT:
                piActionGroupBuilder.withType(PiActionGroup.Type.SELECT);
                break;
            default:
                throw new EncodeException(format("Action profile type %s is not supported",
                                                 actionProfileGroup.getType()));
        }

        Map<Integer, Integer> memberWeights = Maps.newHashMap();
        actionProfileGroup.getMembersList().forEach(member -> {
            int weight = member.getWeight();
            if (weight < 1) {
                // FIXME: currently PI has a bug which will always return weight 0
                // ONOS won't accept group member with weight 0
                weight = 1;
            }
            memberWeights.put(member.getMemberId(), weight);
        });

        for (ActionProfileMember member : members) {
            if (!memberWeights.containsKey(member.getMemberId())) {
                // Not a member of this group, ignore.
                continue;
            }
            int weight = memberWeights.get(member.getMemberId());
            piActionGroupBuilder.addMember(ActionProfileMemberEncoder.decode(member, weight, pipeconf));
        }

        return piActionGroupBuilder.build();
    }
}
