/*
 * 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.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.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:
                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()));
            case MPLS_PUSH:
                L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
                        (L2ModificationInstruction.PushHeaderInstructions) l2m;
                return factory.actions().pushMpls(EthType.of(pushHeaderInstructions
                                                             .ethernetType()));
            case MPLS_POP:
                L2ModificationInstruction.PushHeaderInstructions popHeaderInstructions =
                        (L2ModificationInstruction.PushHeaderInstructions) l2m;
                return factory.actions().popMpls(EthType.of(popHeaderInstructions
                                                            .ethernetType()));
            case MPLS_LABEL:
                L2ModificationInstruction.ModMplsLabelInstruction mplsLabel =
                        (L2ModificationInstruction.ModMplsLabelInstruction) l2m;
                oxm = factory.oxms().mplsLabel(U32.of(mplsLabel.label()
                        .longValue()));
                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;
    }
}

