/*
* Copyright 2016 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.openstacknetworking.switching;

import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.TpPort;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.openstackinterface.OpenstackInterfaceService;
import org.onosproject.openstackinterface.OpenstackSecurityGroup;
import org.onosproject.openstackinterface.OpenstackSecurityGroupRule;
import org.onosproject.openstacknetworking.OpenstackPortInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * Populates flows rules for Security Groups of VMs.
 *
 */
public class OpenstackSecurityGroupRulePopulator {

    private static Logger log = LoggerFactory
            .getLogger(OpenstackSecurityGroupRulePopulator.class);

    private OpenstackInterfaceService openstackService;
    private FlowObjectiveService flowObjectiveService;

    private ApplicationId appId;

    private static final String PROTO_ICMP = "ICMP";
    private static final String PROTO_TCP = "TCP";
    private static final String PROTO_UDP = "UDP";

    private static final String ETHTYPE_IPV4 = "IPV4";

    private static final IpPrefix IP_PREFIX_ANY = Ip4Prefix.valueOf("0.0.0.0/0");

    private static final int ACL_RULE_PRIORITY = 30000;

    /**
     * Constructor.
     *
     * @param appId application ID
     * @param openstackService OpenStack interface service
     * @param flowObjectiveService flow objective service
     */
    public OpenstackSecurityGroupRulePopulator(ApplicationId appId, OpenstackInterfaceService openstackService,
                                               FlowObjectiveService flowObjectiveService) {
        this.appId = appId;
        this.openstackService = openstackService;
        this.flowObjectiveService = flowObjectiveService;
    }

    /**
     * Populates flow rules for security groups.
     *
     * @param id Device ID
     * @param sgId Security Group ID
     * @param vmIp VM IP address
     * @param portInfoMap Port Info map
     */
    public void populateSecurityGroupRules(DeviceId id, String sgId, Ip4Address vmIp,
                                           Map<String, OpenstackPortInfo> portInfoMap) {
        OpenstackSecurityGroup securityGroup = openstackService.getSecurityGroup(sgId);
        if (securityGroup != null) {
            securityGroup.rules().stream().forEach(sgRule -> {
                if (sgRule.remoteGroupId() != null && !sgRule.remoteGroupId().equals("null")) {
                    openstackService.ports().stream()
                        .filter(port -> port.securityGroups().contains(sgRule.remoteGroupId()))
                        .flatMap(port -> port.fixedIps().values().stream())
                        .forEach(remoteIp -> setSecurityGroupRule(id, sgRule,
                                vmIp, IpPrefix.valueOf((IpAddress) remoteIp, 32)));
                } else {
                    setSecurityGroupRule(id, sgRule, vmIp, sgRule.remoteIpPrefix());
                }
            });

            openstackService.ports().stream().forEach(osPort ->
                osPort.securityGroups().stream().forEach(remoteVmSgId -> {
                    OpenstackSecurityGroup remoteVmSg = openstackService.getSecurityGroup(remoteVmSgId);
                    remoteVmSg.rules().stream()
                        .filter(remoteVmSgRule -> remoteVmSgRule.remoteGroupId().equals(sgId))
                        .forEach(remoteVmSgRule -> {
                            Ip4Address remoteVmIp =
                                    (Ip4Address) osPort.fixedIps().values().stream().findAny().orElse(null);
                            OpenstackPortInfo osPortInfo = portInfoMap.get(OpenstackSwitchingManager.PORTNAME_PREFIX_VM
                                    + osPort.id().substring(0, 11));
                            if (osPortInfo != null && remoteVmIp != null) {
                                setSecurityGroupRule(osPortInfo.deviceId(), remoteVmSgRule, remoteVmIp,
                                        IpPrefix.valueOf(vmIp, 32));
                            }
                        });
                }));
        }
    }

    /**
     * Removes flow rules for security groups.
     *
     * @param id Device ID
     * @param sgId Security Group ID to remove
     * @param vmIp VM IP address
     * @param portInfoMap port info map
     * @param securityGroupMap security group info map
     */
    public void removeSecurityGroupRules(DeviceId id, String sgId, Ip4Address vmIp,
                                         Map<String, OpenstackPortInfo> portInfoMap,
                                         Map<String, OpenstackSecurityGroup> securityGroupMap) {
        OpenstackSecurityGroup securityGroup = securityGroupMap.get(sgId);
        if (securityGroup != null) {
            securityGroup.rules().stream().forEach(sgRule -> {
                if (sgRule.remoteGroupId() != null && !sgRule.remoteGroupId().equals("null")) {
                    portInfoMap.values().stream()
                            .filter(portInfo -> portInfo.securityGroups().contains(sgRule.remoteGroupId()))
                            .map(OpenstackPortInfo::ip)
                            .forEach(remoteIp -> {
                                removeSecurityGroupRule(id, sgRule, vmIp, IpPrefix.valueOf(remoteIp, 32));
                            });
                } else {
                    removeSecurityGroupRule(id, sgRule, vmIp, sgRule.remoteIpPrefix());
                }
            });

            portInfoMap.values().stream()
                .forEach(portInfo -> portInfo.securityGroups()
                    .forEach(remoteVmSgId -> {
                        OpenstackSecurityGroup remoteVmSg = securityGroupMap.get(remoteVmSgId);
                        remoteVmSg.rules().stream()
                            .filter(remoteVmSgRule -> remoteVmSgRule.remoteGroupId().equals(sgId))
                            .forEach(remoteVmSgRule -> removeSecurityGroupRule(portInfo.deviceId(),
                                    remoteVmSgRule, portInfo.ip(), IpPrefix.valueOf(vmIp, 32)));
                    }));
        }
    }

    private void setSecurityGroupRule(DeviceId id, OpenstackSecurityGroupRule sgRule,
                                      Ip4Address vmIp, IpPrefix remoteIp) {
        ForwardingObjective.Builder foBuilder = buildFlowObjective(id, sgRule, vmIp, remoteIp);
        if (foBuilder != null) {
            flowObjectiveService.forward(id, foBuilder.add());
        }
    }

    private void removeSecurityGroupRule(DeviceId id, OpenstackSecurityGroupRule sgRule,
                                      Ip4Address vmIp, IpPrefix remoteIp) {
        ForwardingObjective.Builder foBuilder = buildFlowObjective(id, sgRule, vmIp, remoteIp);
        if (foBuilder != null) {
            flowObjectiveService.forward(id, foBuilder.remove());
        }
    }

    ForwardingObjective.Builder buildFlowObjective(DeviceId id, OpenstackSecurityGroupRule sgRule,
                                           Ip4Address vmIp, IpPrefix remoteIp) {
        if (remoteIp != null && remoteIp.equals(IpPrefix.valueOf(vmIp, 32))) {
            return null;
        }
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();

        buildMatchs(sBuilder, sgRule, vmIp, remoteIp);

        ForwardingObjective.Builder foBuilder = DefaultForwardingObjective.builder()
                .withSelector(sBuilder.build())
                .withTreatment(tBuilder.build())
                .withPriority(ACL_RULE_PRIORITY)
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .fromApp(appId);

        return foBuilder;
    }

    private void buildMatchs(TrafficSelector.Builder sBuilder, OpenstackSecurityGroupRule sgRule,
                             Ip4Address vmIp, IpPrefix remoteIp) {
        buildMatchEthType(sBuilder, sgRule.ethertype());
        buildMatchDirection(sBuilder, sgRule.direction(), vmIp);
        buildMatchProto(sBuilder, sgRule.protocol());
        buildMatchPort(sBuilder, sgRule.protocol(), sgRule.direction(), sgRule.portRangeMax(), sgRule.portRangeMin());
        buildMatchRemoteIp(sBuilder, remoteIp, sgRule.direction());
    }

    private void buildMatchDirection(TrafficSelector.Builder sBuilder,
                                     OpenstackSecurityGroupRule.Direction direction, Ip4Address vmIp) {
        if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
            sBuilder.matchIPSrc(IpPrefix.valueOf(vmIp, 32));
        } else {
            sBuilder.matchIPDst(IpPrefix.valueOf(vmIp, 32));
        }
    }

    private void buildMatchEthType(TrafficSelector.Builder sBuilder, String ethertype) {
        // Either IpSrc or IpDst (or both) is set by default, and we need to set EthType as IPv4.
        sBuilder.matchEthType(Ethernet.TYPE_IPV4);
        if (ethertype != null && ethertype != "null" &&
                !ethertype.toUpperCase().equals(ETHTYPE_IPV4)) {
            log.error("EthType {} is not supported yet in Security Group", ethertype);
        }
    }

    private void buildMatchRemoteIp(TrafficSelector.Builder sBuilder, IpPrefix remoteIpPrefix,
                                                       OpenstackSecurityGroupRule.Direction direction) {
        if (remoteIpPrefix != null && !remoteIpPrefix.getIp4Prefix().equals(IP_PREFIX_ANY)) {
            if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
                sBuilder.matchIPDst(remoteIpPrefix);
            } else {
                sBuilder.matchIPSrc(remoteIpPrefix);
            }
        }
    }

    private void buildMatchProto(TrafficSelector.Builder sBuilder, String protocol) {
        if (protocol != null) {
            switch (protocol.toUpperCase()) {
                case PROTO_ICMP:
                    sBuilder.matchIPProtocol(IPv4.PROTOCOL_ICMP);
                    break;
                case PROTO_TCP:
                    sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
                    break;
                case PROTO_UDP:
                    sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
                    break;
                default:
            }
        }
    }

    private void buildMatchPort(TrafficSelector.Builder sBuilder, String protocol,
                                                   OpenstackSecurityGroupRule.Direction direction,
                                                   int portMin, int portMax) {
        if (portMin > 0 && portMax > 0 && portMin == portMax) {
            if (protocol.toUpperCase().equals(PROTO_TCP)) {
                if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
                    sBuilder.matchTcpDst(TpPort.tpPort(portMax));
                } else {
                    sBuilder.matchTcpSrc(TpPort.tpPort(portMax));
                }
            } else if (protocol.toUpperCase().equals(PROTO_UDP)) {
                if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
                    sBuilder.matchUdpDst(TpPort.tpPort(portMax));
                } else {
                    sBuilder.matchUdpSrc(TpPort.tpPort(portMax));
                }
            }
        }
    }
}
