/*
* Copyright 2016-present 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 com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.TpPort;
import org.onlab.util.Tools;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
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.OpenstackPort;
import org.onosproject.openstackinterface.OpenstackSecurityGroup;
import org.onosproject.openstackinterface.OpenstackSecurityGroupRule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static org.onosproject.openstacknetworking.switching.Constants.*;

/**
 * Populates flows rules for Security Groups of VMs.
 *
 */
@Component(immediate = true)
public class OpenstackSecurityGroupRulePopulator extends AbstractVmHandler {

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected OpenstackInterfaceService openstackService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowObjectiveService flowObjectiveService;

    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 final Map<Host, Set<SecurityGroupRule>> securityGroupRuleMap = Maps.newConcurrentMap();

    @Activate
    protected void activate() {
        super.activate();
    }

    @Deactivate
    protected void deactivate() {
        super.deactivate();
    }

    // TODO call this when port is updated from OpenStack
    public void updateSecurityGroup(OpenstackPort osPort) {
        if (!osPort.status().equals(OpenstackPort.PortStatus.ACTIVE)) {
            return;
        }

        Optional<Host> host = getVmByPortId(osPort.id());
        if (!host.isPresent()) {
            log.warn("No host found with {}", osPort);
            return;
        }
        eventExecutor.execute(() -> updateSecurityGroupRules(host.get(), true));
    }

    /**
     * Populates security group rules for all VMs in the supplied tenant ID.
     * VMs in the same tenant tend to be engaged to each other by sharing the
     * same security groups or setting the remote to another security group.
     * To make the implementation simpler and robust, it tries to reinstall
     * security group rules for all the VMs in the same tenant whenever a new
     * VM is detected or port is updated.
     *
     * @param tenantId tenant id to update security group rules
     */
    private void populateSecurityGroupRules(String tenantId, boolean install) {
        securityGroupRuleMap.entrySet().stream()
                .filter(entry -> getTenantId(entry.getKey()).equals(tenantId))
                .forEach(entry -> {
                    Host local = entry.getKey();
                    entry.getValue().stream().forEach(sgRule -> {
                        setSecurityGroupRule(local.location().deviceId(),
                                sgRule.rule(),
                                getIp(local),
                                sgRule.remoteIp(), install);
                    });
                });
        log.debug("Updated security group rules for {}", tenantId);
    }

    private void setSecurityGroupRule(DeviceId deviceId, OpenstackSecurityGroupRule sgRule,
                                      Ip4Address vmIp, IpPrefix remoteIp,
                                      boolean install) {
        ForwardingObjective.Builder foBuilder = buildFlowObjective(sgRule, vmIp, remoteIp);
        if (foBuilder == null) {
            return;
        }

        if (install) {
            flowObjectiveService.forward(deviceId, foBuilder.add());
        } else {
            flowObjectiveService.forward(deviceId, foBuilder.remove());
        }
    }

    private ForwardingObjective.Builder buildFlowObjective(OpenstackSecurityGroupRule sgRule,
                                                           Ip4Address vmIp,
                                                           IpPrefix remoteIp) {
        if (remoteIp != null && remoteIp.equals(IpPrefix.valueOf(vmIp, 32))) {
            // do nothing if the remote IP is my IP
            return null;
        }

        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        buildMatchs(sBuilder, sgRule, vmIp, remoteIp);

        return DefaultForwardingObjective.builder()
                .withSelector(sBuilder.build())
                .withTreatment(DefaultTrafficTreatment.builder().build())
                .withPriority(ACL_RULE_PRIORITY)
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .fromApp(appId);
    }

    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 && !Objects.equals(etherType, "null") &&
                !etherType.toUpperCase().equals(ETHTYPE_IPV4)) {
            log.debug("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));
                }
            }
        }
    }

    private void updateSecurityGroupRulesMap(Host host) {
        OpenstackPort osPort = openstackService.port(host.annotations().value(PORT_ID));
        if (osPort == null) {
            log.debug("Failed to get OpenStack port information for {}", host);
            return;
        }

        Set<SecurityGroupRule> rules = Sets.newHashSet();
        osPort.securityGroups().stream().forEach(sgId -> {
            OpenstackSecurityGroup osSecGroup = openstackService.securityGroup(sgId);
            if (osSecGroup != null) {
                osSecGroup.rules().stream().forEach(rule -> rules.addAll(getSgRules(rule)));
            } else {
                // TODO handle the case that the security group removed
                log.warn("Failed to get security group {}", sgId);
            }
        });
        securityGroupRuleMap.put(host, rules);
    }

    /**
     * Returns set of security group rules with individual remote IP by
     * converting remote group to actual IP address.
     *
     * @param sgRule security group rule
     * @return set of security group rules
     */
    private Set<SecurityGroupRule> getSgRules(OpenstackSecurityGroupRule sgRule) {
        Set<SecurityGroupRule> sgRules = Sets.newHashSet();
        if (sgRule.remoteGroupId() != null && !sgRule.remoteGroupId().equals("null")) {
            sgRules = getRemoteIps(sgRule.tenantId(), sgRule.remoteGroupId())
                    .stream()
                    .map(remoteIp -> new SecurityGroupRule(sgRule, remoteIp))
                    .collect(Collectors.toSet());
        } else {
            sgRules.add(new SecurityGroupRule(sgRule, sgRule.remoteIpPrefix()));
        }
        return sgRules;
    }

    /**
     * Returns a set of host IP addresses engaged with supplied security group ID.
     * It only searches a VM in the same tenant boundary.
     *
     * @param tenantId tenant id
     * @param sgId security group id
     * @return set of ip addresses in ip prefix format
     */
    private Set<IpPrefix> getRemoteIps(String tenantId, String sgId) {
        Set<IpPrefix> remoteIps = Sets.newHashSet();
        securityGroupRuleMap.entrySet().stream()
                .filter(entry -> Objects.equals(getTenantId(entry.getKey()), tenantId))
                .forEach(entry -> {
                    if (entry.getValue().stream()
                            .anyMatch(rule -> rule.rule().secuityGroupId().equals(sgId))) {
                        remoteIps.add(IpPrefix.valueOf(getIp(entry.getKey()), 32));
                    }
                });
        return remoteIps;
    }

    private void updateSecurityGroupRules(Host host, boolean isHostAdded) {
        String tenantId = getTenantId(host);
        populateSecurityGroupRules(tenantId, false);

        if (isHostAdded) {
            updateSecurityGroupRulesMap(host);
        } else {
            securityGroupRuleMap.remove(host);
        }

        Tools.stream(hostService.getHosts())
                .filter(h -> Objects.equals(getTenantId(h), getTenantId(host)))
                .forEach(this::updateSecurityGroupRulesMap);

        populateSecurityGroupRules(tenantId, true);
    }

    @Override
    protected void hostDetected(Host host) {
        updateSecurityGroupRules(host, true);
        log.info("Applied security group rules for {}", host);
    }

    @Override
    protected void hostRemoved(Host host) {
        updateSecurityGroupRules(host, false);
        log.info("Applied security group rules for {}", host);
    }

    private final class SecurityGroupRule {
        private final OpenstackSecurityGroupRule rule;
        private final IpPrefix remoteIp;

        private SecurityGroupRule(OpenstackSecurityGroupRule rule, IpPrefix remoteIp) {
            this.rule = rule;
            this.remoteIp = remoteIp;
        }

        private OpenstackSecurityGroupRule rule() {
            return rule;
        }

        private IpPrefix remoteIp() {
            return remoteIp;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }

            if (obj instanceof SecurityGroupRule) {
                SecurityGroupRule that = (SecurityGroupRule) obj;
                if (Objects.equals(rule, that.rule) &&
                        Objects.equals(remoteIp, that.remoteIp)) {
                    return true;
                }
            }
            return false;
        }

        @Override
        public int hashCode() {
            return Objects.hash(rule, remoteIp);
        }
    }
}
