/*
 * Copyright 2015 Open Networking Laboratory
 *
 * 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.provider.of.group.impl;

import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onosproject.core.GroupId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
import org.projectfloodlight.openflow.protocol.OFBucket;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFGroupAdd;
import org.projectfloodlight.openflow.protocol.OFGroupDelete;
import org.projectfloodlight.openflow.protocol.OFGroupMod;
import org.projectfloodlight.openflow.protocol.OFGroupType;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
import org.projectfloodlight.openflow.types.CircuitSignalID;
import org.projectfloodlight.openflow.types.EthType;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.types.IPv6Address;
import org.projectfloodlight.openflow.types.IPv6FlowLabel;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.OFBooleanValue;
import org.projectfloodlight.openflow.types.OFGroup;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.OFVlanVidMatch;
import org.projectfloodlight.openflow.types.U32;
import org.projectfloodlight.openflow.types.VlanPcp;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;

import static org.slf4j.LoggerFactory.getLogger;

/*
 * Builder for GroupMod.
 */
public final class GroupModBuilder {

    private GroupBuckets buckets;
    private GroupId groupId;
    private GroupDescription.Type type;
    private OFFactory factory;
    private Long xid;

    private final Logger log = getLogger(getClass());

    private static final int OFPCML_NO_BUFFER = 0xffff;

    private GroupModBuilder(GroupBuckets buckets, GroupId groupId,
                             GroupDescription.Type type, OFFactory factory,
                             Optional<Long> xid) {
        this.buckets = buckets;
        this.groupId = groupId;
        this.type = type;
        this.factory = factory;
        this.xid = xid.orElse((long) 0);
    }

    /**
     * Creates a builder for GroupMod.
     *
     * @param buckets GroupBuckets object
     * @param groupId Group Id to create
     * @param type Group type
     * @param factory OFFactory object
     * @param xid transaction ID
     * @return GroupModBuilder object
     */
    public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
                                          GroupDescription.Type type, OFFactory factory,
                                          Optional<Long> xid) {

        return new GroupModBuilder(buckets, groupId, type, factory, xid);
    }

    /**
     * Builds the GroupAdd OF message.
     *
     * @return GroupAdd OF message
     */
    public OFGroupAdd buildGroupAdd() {

        List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
        for (GroupBucket bucket: buckets.buckets()) {
            List<OFAction> actions = buildActions(bucket.treatment());

            OFBucket.Builder bucketBuilder = factory.buildBucket();
            bucketBuilder.setActions(actions);
            if (type == GroupDescription.Type.SELECT) {
                bucketBuilder.setWeight(1);
            }
            bucketBuilder.setWatchGroup(OFGroup.ANY);
            bucketBuilder.setWatchPort(OFPort.ANY);
            OFBucket ofBucket = bucketBuilder.build();
            ofBuckets.add(ofBucket);
        }

        OFGroupAdd groupMsg = factory.buildGroupAdd()
                .setGroup(OFGroup.of(groupId.id()))
                .setBuckets(ofBuckets)
                .setGroupType(getOFGroupType(type))
                .setXid(xid)
                .build();

        return groupMsg;
    }

    /**
     * Builds the GroupMod OF message.
     *
     * @return GroupMod OF message
     */
    public OFGroupMod buildGroupMod() {
        List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
        for (GroupBucket bucket: buckets.buckets()) {
            List<OFAction> actions = buildActions(bucket.treatment());

            OFBucket.Builder bucketBuilder = factory.buildBucket();
            bucketBuilder.setActions(actions);
            if (type == GroupDescription.Type.SELECT) {
                bucketBuilder.setWeight(1);
            }
            bucketBuilder.setWatchGroup(OFGroup.ANY);
            bucketBuilder.setWatchPort(OFPort.ANY);
            OFBucket ofBucket = bucketBuilder.build();
            ofBuckets.add(ofBucket);
        }

        OFGroupMod groupMsg = factory.buildGroupModify()
                .setGroup(OFGroup.of(groupId.id()))
                .setBuckets(ofBuckets)
                .setGroupType(getOFGroupType(type))
                .setXid(xid)
                .build();

        return groupMsg;
    }

    /**
     * Builds the GroupDel OF message.
     *
     * @return GroupDel OF message
     */
    public OFGroupDelete buildGroupDel() {

        OFGroupDelete groupMsg = factory.buildGroupDelete()
                .setGroup(OFGroup.of(groupId.id()))
                .setGroupType(OFGroupType.SELECT)
                .setXid(xid)
                .build();

        return groupMsg;
    }

    private List<OFAction> buildActions(TrafficTreatment treatment) {
        if (treatment == null) {
            return Collections.emptyList();
        }

        List<OFAction> actions = new LinkedList<>();
        for (Instruction i : treatment.allInstructions()) {
            switch (i.type()) {
                case DROP:
                    log.warn("Saw drop action; assigning drop action");
                    return Collections.emptyList();
                case L0MODIFICATION:
                    actions.add(buildL0Modification(i));
                    break;
                case L2MODIFICATION:
                    actions.add(buildL2Modification(i));
                    break;
                case L3MODIFICATION:
                    actions.add(buildL3Modification(i));
                    break;
                case OUTPUT:
                    Instructions.OutputInstruction out =
                            (Instructions.OutputInstruction) i;
                    OFActionOutput.Builder action = factory.actions().buildOutput()
                            .setPort(OFPort.of((int) out.port().toLong()));
                    if (out.port().equals(PortNumber.CONTROLLER)) {
                        action.setMaxLen(OFPCML_NO_BUFFER);
                    }
                    actions.add(action.build());
                    break;
                case GROUP:
                    Instructions.GroupInstruction grp =
                            (Instructions.GroupInstruction) i;
                    OFActionGroup.Builder actgrp = factory.actions().buildGroup()
                            .setGroup(OFGroup.of(grp.groupId().id()));
                    actions.add(actgrp.build());
                    break;
                default:
                    log.warn("Instruction type {} not yet implemented.", i.type());
            }
        }

        return actions;
    }

    private OFAction buildL0Modification(Instruction i) {
        L0ModificationInstruction l0m = (L0ModificationInstruction) i;
        switch (l0m.subtype()) {
            case LAMBDA:
                L0ModificationInstruction.ModLambdaInstruction ml =
                        (L0ModificationInstruction.ModLambdaInstruction) i;
                return factory.actions().circuit(factory.oxms().ochSigidBasic(
                        new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1)));
            default:
                log.warn("Unimplemented action type {}.", l0m.subtype());
                break;
        }
        return null;
    }

    private OFAction buildL2Modification(Instruction i) {
        L2ModificationInstruction l2m = (L2ModificationInstruction) i;
        L2ModificationInstruction.ModEtherInstruction eth;
        OFOxm<?> oxm = null;
        switch (l2m.subtype()) {
            case ETH_DST:
                eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
                oxm = factory.oxms().ethDst(MacAddress.of(eth.mac().toLong()));
                break;
            case ETH_SRC:
                eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
                oxm = factory.oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
                break;
            case VLAN_ID:
                L2ModificationInstruction.ModVlanIdInstruction vlanId =
                        (L2ModificationInstruction.ModVlanIdInstruction) l2m;
                oxm = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
                break;
            case VLAN_PCP:
                L2ModificationInstruction.ModVlanPcpInstruction vlanPcp =
                        (L2ModificationInstruction.ModVlanPcpInstruction) l2m;
                oxm = factory.oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
                break;
            case VLAN_POP:
                return factory.actions().popVlan();
            case VLAN_PUSH:
                L2ModificationInstruction.PushHeaderInstructions pushVlanInstruction
                        = (L2ModificationInstruction.PushHeaderInstructions) l2m;
                return factory.actions().pushVlan(
                        EthType.of(pushVlanInstruction.ethernetType().toShort()));
            case MPLS_PUSH:
                L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
                        (L2ModificationInstruction.PushHeaderInstructions) l2m;
                return factory.actions().pushMpls(EthType.of(pushHeaderInstructions
                                                             .ethernetType().toShort()));
            case MPLS_POP:
                L2ModificationInstruction.PushHeaderInstructions popHeaderInstructions =
                        (L2ModificationInstruction.PushHeaderInstructions) l2m;
                return factory.actions().popMpls(EthType.of(popHeaderInstructions
                                                            .ethernetType().toShort()));
            case MPLS_LABEL:
                L2ModificationInstruction.ModMplsLabelInstruction mplsLabel =
                        (L2ModificationInstruction.ModMplsLabelInstruction) l2m;
                oxm = factory.oxms().mplsLabel(U32.of(mplsLabel.label()
                        .longValue()));
                break;
            case MPLS_BOS:
                L2ModificationInstruction.ModMplsBosInstruction mplsBos =
                        (L2ModificationInstruction.ModMplsBosInstruction) l2m;
                oxm = factory.oxms()
                        .mplsBos(mplsBos.mplsBos() ? OFBooleanValue.TRUE
                                                   : OFBooleanValue.FALSE);
                break;
            case DEC_MPLS_TTL:
                return factory.actions().decMplsTtl();
            default:
                log.warn("Unimplemented action type {}.", l2m.subtype());
                break;
        }

        if (oxm != null) {
            return factory.actions().buildSetField().setField(oxm).build();
        }
        return null;
    }

    private OFAction buildL3Modification(Instruction i) {
        L3ModificationInstruction l3m = (L3ModificationInstruction) i;
        L3ModificationInstruction.ModIPInstruction ip;
        Ip4Address ip4;
        Ip6Address ip6;
        OFOxm<?> oxm = null;
        switch (l3m.subtype()) {
            case IPV4_SRC:
                ip = (L3ModificationInstruction.ModIPInstruction) i;
                ip4 = ip.ip().getIp4Address();
                oxm = factory.oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
                break;
            case IPV4_DST:
                ip = (L3ModificationInstruction.ModIPInstruction) i;
                ip4 = ip.ip().getIp4Address();
                oxm = factory.oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
                break;
            case IPV6_SRC:
                ip = (L3ModificationInstruction.ModIPInstruction) i;
                ip6 = ip.ip().getIp6Address();
                oxm = factory.oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
                break;
            case IPV6_DST:
                ip = (L3ModificationInstruction.ModIPInstruction) i;
                ip6 = ip.ip().getIp6Address();
                oxm = factory.oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
                break;
            case IPV6_FLABEL:
                L3ModificationInstruction.ModIPv6FlowLabelInstruction flowLabelInstruction =
                    (L3ModificationInstruction.ModIPv6FlowLabelInstruction) i;
                int flowLabel = flowLabelInstruction.flowLabel();
                oxm = factory.oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
                break;
            case DEC_TTL:
                return factory.actions().decNwTtl();
            case TTL_IN:
                return factory.actions().copyTtlIn();
            case TTL_OUT:
                return factory.actions().copyTtlOut();
            default:
                log.warn("Unimplemented action type {}.", l3m.subtype());
                break;
        }

        if (oxm != null) {
            return factory.actions().buildSetField().setField(oxm).build();
        }
        return null;
    }

    private OFGroupType getOFGroupType(GroupDescription.Type groupType) {
        switch (groupType) {
            case INDIRECT:
                return OFGroupType.INDIRECT;
            case SELECT:
                return OFGroupType.SELECT;
            case FAILOVER:
                return OFGroupType.FF;
            case ALL:
                return OFGroupType.ALL;
            default:
                log.error("Unsupported group type : {}", groupType);
                break;
        }
        return null;
    }
}

