/*
 * Copyright 2015 Open Networking Laboratory
 * Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China
 * Advisers: Keqiu Li and Heng Qi
 * This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002)
 * and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
 *
 * 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.onos.acl.impl;

import org.onos.acl.AclRule;
import org.onos.acl.AclService;
import org.onos.acl.AclStore;
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.apache.felix.scr.annotations.Service;
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.onos.acl.RuleId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.IdGenerator;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowEntry;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.slf4j.Logger;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Implementation of the ACL service.
 */
@Component(immediate = true)
@Service
public class AclManager implements AclService {

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowRuleService flowRuleService;
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected HostService hostService;
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected MastershipService mastershipService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected AclStore aclStore;

    private final Logger log = getLogger(getClass());
    private ApplicationId appId;
    private final HostListener hostListener = new InternalHostListener();
    private IdGenerator idGenerator;

    /**
     * Checks if the given IP address is in the given CIDR address.
     */
    private boolean checkIpInCIDR(Ip4Address ip, Ip4Prefix cidr) {
        int offset = 32 - cidr.prefixLength();
        int cidrPrefix = cidr.address().toInt();
        int ipIntValue = ip.toInt();
        cidrPrefix = cidrPrefix >> offset;
        ipIntValue = ipIntValue >> offset;
        cidrPrefix = cidrPrefix << offset;
        ipIntValue = ipIntValue << offset;

        return (cidrPrefix == ipIntValue);
    }

    private class InternalHostListener implements HostListener {

        /**
         * Generate new ACL flow rules for new host following the given ACL rule.
         */
        private void processHostAddedEvent(HostEvent event, AclRule rule) {
            DeviceId deviceId = event.subject().location().deviceId();
            for (IpAddress address : event.subject().ipAddresses()) {
                if ((rule.srcIp() != null) ?
                        (checkIpInCIDR(address.getIp4Address(), rule.srcIp())) :
                        (checkIpInCIDR(address.getIp4Address(), rule.dstIp()))) {
                    if (!aclStore.checkIfRuleWorksInDevice(rule.id(), deviceId)) {
                        List<RuleId> allowingRuleList = aclStore
                                .getAllowingRuleByDenyingRule(rule.id());
                        if (allowingRuleList != null) {
                            for (RuleId allowingRuleId : allowingRuleList) {
                                generateACLFlow(aclStore.getAclRule(allowingRuleId), deviceId);
                            }
                        }
                        generateACLFlow(rule, deviceId);
                    }
                }
            }
        }

        @Override
        public void event(HostEvent event) {
            // if a new host appears and an existing rule denies
            // its traffic, a new ACL flow rule is generated.
            if (event.type() == HostEvent.Type.HOST_ADDED) {
                DeviceId deviceId = event.subject().location().deviceId();
                if (mastershipService.getLocalRole(deviceId) == MastershipRole.MASTER) {
                    for (AclRule rule : aclStore.getAclRules()) {
                        if (rule.action() != AclRule.Action.ALLOW) {
                            processHostAddedEvent(event, rule);
                        }
                    }
                }
            }
        }
    }

    @Activate
    public void activate() {
        appId = coreService.registerApplication("org.onos.acl");
        hostService.addListener(hostListener);
        idGenerator = coreService.getIdGenerator("acl-ids");
        AclRule.bindIdGenerator(idGenerator);
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        hostService.removeListener(hostListener);
        flowRuleService.removeFlowRulesById(appId);
        aclStore.clearAcl();
        log.info("Stopped");
    }

    @Override
    public List<AclRule> getAclRules() {
        return aclStore.getAclRules();
    }

    /**
     * Checks if the new ACL rule matches an existing rule.
     * If existing allowing rules matches the new denying rule, store the mappings.
     * @return true if the new ACL rule matches an existing rule, false otherwise
     */
    private boolean matchCheck(AclRule newRule) {
        for (AclRule existingRule : aclStore.getAclRules()) {
            if (newRule.checkMatch(existingRule)) {
                return true;
            }

            if (existingRule.action() == AclRule.Action.ALLOW
                    && newRule.action() == AclRule.Action.DENY) {
                if (existingRule.checkMatch(newRule)) {
                    aclStore.addDenyToAllowMapping(newRule.id(), existingRule.id());
                }
            }
        }
        return false;
    }

    @Override
    public boolean addAclRule(AclRule rule) {
        if (matchCheck(rule)) {
            return false;
        }
        aclStore.addAclRule(rule);
        log.info("ACL rule(id:{}) is added.", rule.id());
        if (rule.action() != AclRule.Action.ALLOW) {
            enforceRuleAdding(rule);
        }
        return true;
    }

    /**
     * Gets a set containing all devices connecting with the hosts
     * whose IP address is in the given CIDR IP address.
     */
    private Set<DeviceId> getDeviceIdSet(Ip4Prefix cidrAddr) {
        Set<DeviceId> deviceIdSet = new HashSet<>();
        final Iterable<Host> hosts = hostService.getHosts();

        if (cidrAddr.prefixLength() != 32) {
            for (Host h : hosts) {
                for (IpAddress a : h.ipAddresses()) {
                    if (checkIpInCIDR(a.getIp4Address(), cidrAddr)) {
                        deviceIdSet.add(h.location().deviceId());
                    }
                }
            }
        } else {
            for (Host h : hosts) {
                for (IpAddress a : h.ipAddresses()) {
                    if (checkIpInCIDR(a.getIp4Address(), cidrAddr)) {
                        deviceIdSet.add(h.location().deviceId());
                        return deviceIdSet;
                    }
                }
            }
        }
        return deviceIdSet;
    }

    /**
     * Enforces denying ACL rule by ACL flow rules.
     */
    private void enforceRuleAdding(AclRule rule) {
        Set<DeviceId> dpidSet;
        if (rule.srcIp() != null) {
            dpidSet = getDeviceIdSet(rule.srcIp());
        } else {
            dpidSet = getDeviceIdSet(rule.dstIp());
        }

        for (DeviceId deviceId : dpidSet) {
            List<RuleId> allowingRuleList = aclStore.getAllowingRuleByDenyingRule(rule.id());
            if (allowingRuleList != null) {
                for (RuleId allowingRuleId : allowingRuleList) {
                    generateACLFlow(aclStore.getAclRule(allowingRuleId), deviceId);
                }
            }
            generateACLFlow(rule, deviceId);
        }
    }

    /**
     * Generates ACL flow rule according to ACL rule
     * and install it into related device.
     */
    private void generateACLFlow(AclRule rule, DeviceId deviceId) {
        if (rule == null || aclStore.checkIfRuleWorksInDevice(rule.id(), deviceId)) {
            return;
        }

        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        FlowEntry.Builder flowEntry = DefaultFlowEntry.builder();

        selectorBuilder.matchEthType(Ethernet.TYPE_IPV4);
        if (rule.srcIp() != null) {
            selectorBuilder.matchIPSrc(rule.srcIp());
            if (rule.dstIp() != null) {
                selectorBuilder.matchIPDst(rule.dstIp());
            }
        } else {
            selectorBuilder.matchIPDst(rule.dstIp());
        }
        if (rule.ipProto() != 0) {
            selectorBuilder.matchIPProtocol(Integer.valueOf(rule.ipProto()).byteValue());
        }
        if (rule.dstTpPort() != 0) {
            switch (rule.ipProto()) {
                case IPv4.PROTOCOL_TCP:
                    selectorBuilder.matchTcpDst(rule.dstTpPort());
                    break;
                case IPv4.PROTOCOL_UDP:
                    selectorBuilder.matchUdpDst(rule.dstTpPort());
                    break;
                default:
                    break;
            }
        }
        if (rule.action() == AclRule.Action.ALLOW) {
            treatment.add(Instructions.createOutput(PortNumber.CONTROLLER));
        }
        flowEntry.forDevice(deviceId);
        flowEntry.withPriority(aclStore.getPriorityByDevice(deviceId));
        flowEntry.withSelector(selectorBuilder.build());
        flowEntry.withTreatment(treatment.build());
        flowEntry.fromApp(appId);
        flowEntry.makePermanent();
        // install flow rule
        flowRuleService.applyFlowRules(flowEntry.build());
        log.debug("ACL flow rule {} is installed in {}.", flowEntry.build(), deviceId);
        aclStore.addRuleToFlowMapping(rule.id(), flowEntry.build());
        aclStore.addRuleToDeviceMapping(rule.id(), deviceId);
    }

    @Override
    public void removeAclRule(RuleId ruleId) {
        aclStore.removeAclRule(ruleId);
        log.info("ACL rule(id:{}) is removed.", ruleId);
        enforceRuleRemoving(ruleId);
    }

    /**
     * Enforces removing an existing ACL rule.
     */
    private void enforceRuleRemoving(RuleId ruleId) {
        Set<FlowRule> flowSet = aclStore.getFlowByRule(ruleId);
        if (flowSet != null) {
            for (FlowRule flowRule : flowSet) {
                flowRuleService.removeFlowRules(flowRule);
                log.debug("ACL flow rule {} is removed from {}.", flowRule.toString(), flowRule.deviceId().toString());
            }
        }
        aclStore.removeRuleToFlowMapping(ruleId);
        aclStore.removeRuleToDeviceMapping(ruleId);
        aclStore.removeDenyToAllowMapping(ruleId);
    }

    @Override
    public void clearAcl() {
        aclStore.clearAcl();
        flowRuleService.removeFlowRulesById(appId);
        log.info("ACL is cleared.");
    }

}
