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

import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onosproject.core.GroupId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.driver.DefaultDriverData;
import org.onosproject.net.driver.DefaultDriverHandler;
import org.onosproject.net.driver.Driver;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.ExtensionTreatment;
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.flow.instructions.L4ModificationInstruction;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.openflow.controller.ExtensionTreatmentInterpreter;
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.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.TransportPort;
import org.projectfloodlight.openflow.types.U32;
import org.projectfloodlight.openflow.types.U64;
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 Optional<DriverService> driverService;

    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);
    }

    private GroupModBuilder(GroupBuckets buckets, GroupId groupId,
                            GroupDescription.Type type, OFFactory factory,
                            Optional<Long> xid, Optional<DriverService> driverService) {
       this.buckets = buckets;
       this.groupId = groupId;
       this.type = type;
       this.factory = factory;
       this.xid = xid.orElse((long) 0);
       this.driverService = driverService;
   }
    /**
     * 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);
    }

    /**
     * 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
     * @param driverService driver Service
     * @return GroupModBuilder object
     */
    public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
                                          GroupDescription.Type type, OFFactory factory,
                                          Optional<Long> xid, Optional<DriverService> driverService) {

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

    private OFBucket.Builder ofBucketBuilder(GroupBucket bucket) {
        OFBucket.Builder bucketBuilder = factory.buildBucket();
        List<OFAction> actions = buildActions(bucket.treatment());
        bucketBuilder.setActions(actions);
        if (type == GroupDescription.Type.SELECT) {
            bucketBuilder.setWeight(bucket.weight());
        }
        if (type == GroupDescription.Type.FAILOVER && bucket.watchPort() != null) {
            bucketBuilder.setWatchPort(OFPort.of((int) bucket.watchPort().toLong()));
        } else {
            bucketBuilder.setWatchPort(OFPort.ANY);
        }
        if (type == GroupDescription.Type.FAILOVER && bucket.watchGroup() != null) {
            bucketBuilder.setWatchGroup(OFGroup.of(bucket.watchGroup().id()));
        } else {
            bucketBuilder.setWatchGroup(OFGroup.ANY);
        }
        return bucketBuilder;
    }

    /**
     * Builds the GroupAdd OF message.
     *
     * @return GroupAdd OF message
     */
    public OFGroupAdd buildGroupAdd() {
        // Build group add
        List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
        for (GroupBucket bucket: buckets.buckets()) {
            OFBucket ofBucket = ofBucketBuilder(bucket).build();
            ofBuckets.add(ofBucket);
        }
        // Build the msg and return
        return factory.buildGroupAdd()
                .setGroup(OFGroup.of(groupId.id()))
                .setBuckets(ofBuckets)
                .setGroupType(getOFGroupType(type))
                .setXid(xid)
                .build();
     }

     /**
      * Builds the GroupMod OF message.
      *
      * @return GroupMod OF message
      */
     public OFGroupMod buildGroupMod() {
         // Build group mod
         List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
         for (GroupBucket bucket: buckets.buckets()) {
             OFBucket ofBucket = ofBucketBuilder(bucket).build();
             ofBuckets.add(ofBucket);
         }
         // Build the msg and return
         return factory.buildGroupModify()
                 .setGroup(OFGroup.of(groupId.id()))
                 .setBuckets(ofBuckets)
                 .setGroupType(getOFGroupType(type))
                 .setXid(xid)
                 .build();
    }

    /**
     * Builds the GroupDel OF message.
     *
     * @return GroupDel OF message
     */
    public OFGroupDelete buildGroupDel() {
        // Build the msg and return
        return factory.buildGroupDelete()
                .setGroup(OFGroup.of(groupId.id()))
                .setGroupType(getOFGroupType(type))
                .setXid(xid)
                .build();
    }

    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 L0MODIFICATION:
                    actions.add(buildL0Modification(i));
                    break;
                case L2MODIFICATION:
                    actions.add(buildL2Modification(i));
                    break;
                case L3MODIFICATION:
                    actions.add(buildL3Modification(i));
                    break;
                case L4MODIFICATION:
                    actions.add(buildL4Modification(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;
                case EXTENSION:
                    Instructions.ExtensionInstructionWrapper wrapper =
                    (Instructions.ExtensionInstructionWrapper) i;
                    actions.add(buildExtensionAction(
                            wrapper.extensionInstruction(), wrapper.deviceId()));
                    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()) {
            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.ModVlanHeaderInstruction pushVlanInstruction
                        = (L2ModificationInstruction.ModVlanHeaderInstruction) l2m;
                return factory.actions().pushVlan(
                        EthType.of(pushVlanInstruction.ethernetType().toShort()));
            case MPLS_PUSH:
                L2ModificationInstruction.ModMplsHeaderInstruction pushHeaderInstructions =
                        (L2ModificationInstruction.ModMplsHeaderInstruction) l2m;
                return factory.actions().pushMpls(EthType.of(pushHeaderInstructions
                                                             .ethernetType().toShort()));
            case MPLS_POP:
                L2ModificationInstruction.ModMplsHeaderInstruction popHeaderInstructions =
                        (L2ModificationInstruction.ModMplsHeaderInstruction) 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().toInt()));
                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();
            case TUNNEL_ID:
                L2ModificationInstruction.ModTunnelIdInstruction tunnelId =
                        (L2ModificationInstruction.ModTunnelIdInstruction) l2m;
                oxm = factory.oxms().tunnelId(U64.of(tunnelId.tunnelId()));
                break;
            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;
    }

    protected OFAction buildL4Modification(Instruction i) {
        L4ModificationInstruction l4m = (L4ModificationInstruction) i;
        L4ModificationInstruction.ModTransportPortInstruction tp;
        OFOxm<?> oxm = null;
        switch (l4m.subtype()) {
            case TCP_SRC:
                tp = (L4ModificationInstruction.ModTransportPortInstruction) l4m;
                oxm = factory.oxms().tcpSrc(TransportPort.of(tp.port().toInt()));
                break;
            case TCP_DST:
                tp = (L4ModificationInstruction.ModTransportPortInstruction) l4m;
                oxm = factory.oxms().tcpDst(TransportPort.of(tp.port().toInt()));
                break;
            case UDP_SRC:
                tp = (L4ModificationInstruction.ModTransportPortInstruction) l4m;
                oxm = factory.oxms().udpSrc(TransportPort.of(tp.port().toInt()));
                break;
            case UDP_DST:
                tp = (L4ModificationInstruction.ModTransportPortInstruction) l4m;
                oxm = factory.oxms().udpDst(TransportPort.of(tp.port().toInt()));
                break;
            default:
                log.warn("Unimplemented action type {}.", l4m.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;
    }

    private OFAction buildExtensionAction(ExtensionTreatment i, DeviceId deviceId) {
        if (!driverService.isPresent()) {
            log.error("No driver service present");
            return null;
        }
        Driver driver = driverService.get().getDriver(deviceId);
        if (driver.hasBehaviour(ExtensionTreatmentInterpreter.class)) {
            DefaultDriverHandler handler =
                    new DefaultDriverHandler(new DefaultDriverData(driver, deviceId));
            ExtensionTreatmentInterpreter interpreter = handler.behaviour(ExtensionTreatmentInterpreter.class);
            return interpreter.mapInstruction(factory, i);
        }

        return null;
    }
}

