/*
 * 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.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
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.Ip4Address;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.dhcp.DhcpService;
import org.onosproject.event.AbstractEvent;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.onosproject.openstackinterface.OpenstackInterfaceService;
import org.onosproject.openstackinterface.OpenstackNetwork;
import org.onosproject.openstackinterface.OpenstackPort;
import org.onosproject.openstackinterface.OpenstackSecurityGroup;
import org.onosproject.openstackinterface.OpenstackSubnet;
import org.onosproject.openstacknetworking.OpenstackPortInfo;
import org.onosproject.openstacknetworking.OpenstackSwitchingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static org.onlab.util.Tools.groupedThreads;

@Service
@Component(immediate = true)
/**
 * Populates forwarding rules for VMs created by Openstack.
 */
public class OpenstackSwitchingManager implements OpenstackSwitchingService {

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected PacketService packetService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected HostService hostService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DhcpService dhcpService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DriverService driverService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigService configService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigRegistry configRegistry;

    public static final String PORTNAME_PREFIX_VM = "tap";
    public static final String PORTNAME_PREFIX_ROUTER = "qr-";
    public static final String PORTNAME_PREFIX_TUNNEL = "vxlan";
    public static final String PORTNAME = "portName";
    private static final String ROUTER_INTERFACE = "network:router_interface";
    public static final String DEVICE_OWNER_GATEWAY = "network:router_gateway";
    public static final String DNS_SERVER_IP = "8.8.8.8";
    private static final String FORWARD_SLASH = "/";


    private ApplicationId appId;

    private OpenstackArpHandler arpHandler;
    private OpenstackSecurityGroupRulePopulator sgRulePopulator;

    private ExecutorService deviceEventExecutorService =
            Executors.newSingleThreadExecutor(groupedThreads("onos/openstackswitching", "device-event"));

    private ExecutorService configEventExecutorService =
            Executors.newSingleThreadExecutor(groupedThreads("onos/openstackswitching", "config-event"));

    private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor();
    private InternalDeviceListener internalDeviceListener = new InternalDeviceListener();
    private InternalHostListener internalHostListener = new InternalHostListener();

    private final Map<String, OpenstackPortInfo> openstackPortInfoMap = Maps.newHashMap();
    private Map<String, OpenstackSecurityGroup> securityGroupMap = Maps.newConcurrentMap();

    private final ConfigFactory configFactory =
            new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY,
                    OpenstackSwitchingConfig.class, "openstackswitching") {
                @Override
                public OpenstackSwitchingConfig createConfig() {
                    return new OpenstackSwitchingConfig();
                }
            };
    private final NetworkConfigListener configListener = new InternalConfigListener();

    private OpenstackSwitchingConfig config;

    @Activate
    protected void activate() {
        appId = coreService
                .registerApplication("org.onosproject.openstackswitching");

        packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1));
        deviceService.addListener(internalDeviceListener);
        hostService.addListener(internalHostListener);
        configRegistry.registerConfigFactory(configFactory);
        configService.addListener(configListener);

        readConfiguration();

        log.info("Started");
    }

    @Deactivate
    protected void deactivate() {
        packetService.removeProcessor(internalPacketProcessor);
        deviceService.removeListener(internalDeviceListener);

        deviceEventExecutorService.shutdown();
        configEventExecutorService.shutdown();
        hostService.removeListener(internalHostListener);
        configService.removeListener(configListener);
        configRegistry.unregisterConfigFactory(configFactory);

        log.info("Stopped");
    }

    @Override
    public void createPorts(OpenstackPort openstackPort) {

        if (!openstackPort.deviceOwner().equals(ROUTER_INTERFACE)
                && !openstackPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)
                && !openstackPort.fixedIps().isEmpty()) {
                registerDhcpInfo(openstackPort);
        }
    }

    @Override
    public void removePort(String uuid) {
        // When VMs are remvoed, the flow rules for the VMs are removed using ONOS port update event.
        // But, when router is removed, no ONOS port event occurs and we need to use Neutron port event.
        // Here we should not touch any rules for VMs.
        log.debug("port {} was removed", uuid);

        String routerPortName = PORTNAME_PREFIX_ROUTER + uuid.substring(0, 11);
        OpenstackPortInfo routerPortInfo = openstackPortInfoMap.get(routerPortName);
        if (routerPortInfo != null) {
            dhcpService.removeStaticMapping(routerPortInfo.mac());
            deviceService.getPorts(routerPortInfo.deviceId()).forEach(port -> {
                String pName = port.annotations().value(PORTNAME);
                if (pName.equals(routerPortName)) {
                    OpenstackSwitchingRulePopulator rulePopulator =
                            new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
                                    deviceService, openstackService, driverService, config);

                    rulePopulator.removeSwitchingRules(port, openstackPortInfoMap);
                    openstackPortInfoMap.remove(routerPortName);
                    return;
                }
            });
        }
    }

    @Override
    public void updatePort(OpenstackPort openstackPort) {
        if (openstackPort.status().equals(OpenstackPort.PortStatus.ACTIVE)) {
            String portName = PORTNAME_PREFIX_VM + openstackPort.id().substring(0, 11);
            OpenstackPortInfo osPortInfo = openstackPortInfoMap.get(portName);
            if (osPortInfo != null) {
                // Remove all security group rules based on the ones stored in security group map.
                osPortInfo.securityGroups().stream().forEach(
                        sgId -> sgRulePopulator.removeSecurityGroupRules(osPortInfo.deviceId(), sgId,
                                osPortInfo.ip(), openstackPortInfoMap, securityGroupMap));
                // Add all security group rules based on the updated security group.
                openstackPort.securityGroups().stream().forEach(
                        sgId -> sgRulePopulator.populateSecurityGroupRules(osPortInfo.deviceId(), sgId,
                                osPortInfo.ip(), openstackPortInfoMap));
                updatePortMap(osPortInfo.deviceId(), portName, openstackService.networks(),
                        openstackService.subnets(), openstackPort);
            }
        }
    }

    @Override
    public void createNetwork(OpenstackNetwork openstackNetwork) {
        //TODO
    }

    @Override
    public void createSubnet(OpenstackSubnet openstackSubnet) {
        //TODO
    }

    @Override
    public Map<String, OpenstackPortInfo> openstackPortInfo() {
        return ImmutableMap.copyOf(this.openstackPortInfoMap);
    }

    private void processPortUpdated(Device device, Port port) {
        String portName = port.annotations().value(PORTNAME);
        synchronized (openstackPortInfoMap) {
            if (portName.startsWith(PORTNAME_PREFIX_VM)) {
                if (port.isEnabled()) {
                    OpenstackSwitchingRulePopulator rulePopulator =
                            new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
                                    deviceService, openstackService, driverService, config);

                    rulePopulator.populateSwitchingRules(device, port);
                    OpenstackPort openstackPort = rulePopulator.openstackPort(port);
                    Ip4Address vmIp = (Ip4Address) openstackPort.fixedIps().values().stream()
                            .findAny().orElseGet(null);
                    openstackPort.securityGroups().stream().forEach(
                            sgId -> sgRulePopulator.populateSecurityGroupRules(device.id(), sgId, vmIp,
                                    openstackPortInfoMap));
                    updatePortMap(device.id(), port.annotations().value(PORTNAME),
                            openstackService.networks(), openstackService.subnets(), openstackPort);

                    //In case portupdate event is driven by vm shutoff from openstack
                } else if (!port.isEnabled() && openstackPortInfoMap.containsKey(portName)) {
                    log.debug("Flowrules according to the port {} were removed", port.number());
                    OpenstackSwitchingRulePopulator rulePopulator =
                            new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
                                    deviceService, openstackService, driverService, config);
                    rulePopulator.removeSwitchingRules(port, openstackPortInfoMap);
                    openstackPortInfoMap.get(portName).securityGroups().stream().forEach(
                            sgId -> sgRulePopulator.removeSecurityGroupRules(device.id(), sgId,
                                    openstackPortInfoMap.get(portName).ip(), openstackPortInfoMap, securityGroupMap));
                    dhcpService.removeStaticMapping(openstackPortInfoMap.get(port.annotations().value(PORTNAME)).mac());
                    openstackPortInfoMap.remove(port.annotations().value(PORTNAME));
                }
            }
        }
    }

    private void processPortRemoved(Port port) {
        log.debug("port {} is removed", port.toString());
    }

    private void initializeFlowRules() {
        OpenstackSwitchingRulePopulator rulePopulator =
                new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
                        deviceService, openstackService, driverService, config);

        Collection<OpenstackNetwork> networks = openstackService.networks();
        Collection<OpenstackSubnet> subnets = openstackService.subnets();

        deviceService.getDevices().forEach(device -> {
                log.debug("device {} num of ports {} ", device.id(),
                        deviceService.getPorts(device.id()).size());
                deviceService.getPorts(device.id()).stream()
                        .filter(port -> port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_VM) ||
                                port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_ROUTER))
                        .forEach(vmPort -> {
                                OpenstackPort osPort = rulePopulator.openstackPort(vmPort);
                                if (osPort != null && !osPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)) {
                                    rulePopulator.populateSwitchingRules(device, vmPort);
                                    Ip4Address vmIp = (Ip4Address) osPort.fixedIps().values().stream()
                                            .findAny().orElseGet(null);
                                    osPort.securityGroups().stream().forEach(
                                            sgId -> sgRulePopulator.populateSecurityGroupRules(device.id(),
                                                    sgId, vmIp, openstackPortInfoMap));
                                    updatePortMap(device.id(), vmPort.annotations().value(PORTNAME), networks,
                                            subnets, osPort);
                                    registerDhcpInfo(osPort);
                                } else {
                                    log.warn("No openstackPort information for port {}", vmPort);
                                }
                            }
                        );
                }
        );
    }

    private void updatePortMap(DeviceId deviceId, String portName, Collection<OpenstackNetwork> networks,
                               Collection<OpenstackSubnet> subnets, OpenstackPort openstackPort) {
        long vni;
        OpenstackNetwork openstackNetwork = networks.stream()
                .filter(n -> n.id().equals(openstackPort.networkId()))
                .findAny().orElse(null);
        if (openstackNetwork != null) {
            vni = Long.parseLong(openstackNetwork.segmentId());
        } else {
            log.debug("updatePortMap failed because there's no OpenstackNetwork matches {}", openstackPort.networkId());
            return;
        }


        OpenstackSubnet openstackSubnet = subnets.stream()
                .filter(n -> n.networkId().equals(openstackPort.networkId()))
                .findFirst().get();

        Ip4Address gatewayIPAddress = Ip4Address.valueOf(openstackSubnet.gatewayIp());

        OpenstackPortInfo.Builder portBuilder = OpenstackPortInfo.builder()
                .setDeviceId(deviceId)
                .setHostIp((Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null))
                .setHostMac(openstackPort.macAddress())
                .setVni(vni)
                .setGatewayIP(gatewayIPAddress)
                .setNetworkId(openstackPort.networkId())
                .setSecurityGroups(openstackPort.securityGroups());

        openstackPortInfoMap.put(portName, portBuilder.build());

        openstackPort.securityGroups().stream().forEach(sgId -> {
            if (!securityGroupMap.containsKey(sgId)) {
                securityGroupMap.put(sgId, openstackService.getSecurityGroup(sgId));
            }
        });
    }

    private void registerDhcpInfo(OpenstackPort openstackPort) {
        Ip4Address ip4Address, subnetMask, gatewayIPAddress, dhcpServer, domainServer;
        OpenstackSubnet openstackSubnet;

        ip4Address = (Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null);

        openstackSubnet = openstackService.subnets().stream()
                .filter(n -> n.networkId().equals(openstackPort.networkId()))
                .findFirst().get();

        subnetMask = Ip4Address.valueOf(buildSubnetMask(openstackSubnet.cidr()));
        gatewayIPAddress = Ip4Address.valueOf(openstackSubnet.gatewayIp());
        dhcpServer = gatewayIPAddress;
        // TODO: supports multiple DNS servers
        if (openstackSubnet.dnsNameservers().isEmpty()) {
            domainServer = Ip4Address.valueOf(DNS_SERVER_IP);
        } else {
            domainServer = openstackSubnet.dnsNameservers().get(0);
        }
        List<Ip4Address> options = ImmutableList.of(subnetMask, dhcpServer, gatewayIPAddress, domainServer);

        dhcpService.setStaticMapping(openstackPort.macAddress(), ip4Address, true, options);
    }

    private byte[] buildSubnetMask(String cidr) {
        int prefix;
        String[] parts = cidr.split(FORWARD_SLASH);
        prefix = Integer.parseInt(parts[1]);
        int mask = 0xffffffff << (32 - prefix);
        byte[] bytes = new byte[]{(byte) (mask >>> 24),
                (byte) (mask >> 16 & 0xff), (byte) (mask >> 8 & 0xff), (byte) (mask & 0xff)};

        return bytes;
    }



    private class InternalPacketProcessor implements PacketProcessor {

        @Override
        public void process(PacketContext context) {
            if (context.isHandled()) {
                return;
            }

            InboundPacket pkt = context.inPacket();
            Ethernet ethernet = pkt.parsed();

            if (ethernet != null && ethernet.getEtherType() == Ethernet.TYPE_ARP) {
                arpHandler.processPacketIn(pkt, openstackPortInfoMap.values());
            }
        }
    }

    private class InternalHostListener implements HostListener {

        @Override
        public void event(HostEvent hostEvent) {
            deviceEventExecutorService.execute(new InternalEventHandler(hostEvent));
        }
    }

    private class InternalDeviceListener implements DeviceListener {

        @Override
        public void event(DeviceEvent deviceEvent) {
            deviceEventExecutorService.execute(new InternalEventHandler(deviceEvent));
        }
    }

    private class InternalEventHandler implements Runnable {

        volatile AbstractEvent event;

        InternalEventHandler(AbstractEvent event) {
            this.event = event;
        }

        @Override
        public void run() {

            if (event instanceof  DeviceEvent) {
                DeviceEvent deviceEvent = (DeviceEvent) event;

                switch (deviceEvent.type()) {
                    case DEVICE_ADDED:
                        log.debug("device {} is added", deviceEvent.subject().id());
                        break;
                    case DEVICE_AVAILABILITY_CHANGED:
                        Device device = deviceEvent.subject();
                        if (deviceService.isAvailable(device.id())) {
                            log.debug("device {} is added", device.id());
                        }
                        break;
                    case PORT_ADDED:
                        processPortUpdated(deviceEvent.subject(), deviceEvent.port());
                        break;
                    case PORT_UPDATED:
                        processPortUpdated(deviceEvent.subject(), deviceEvent.port());
                        break;
                    case PORT_REMOVED:
                        processPortRemoved(deviceEvent.port());
                        break;
                    default:
                        log.debug("Unsupported deviceEvent type {}", deviceEvent.type().toString());
                        break;
                }
            } else if (event instanceof HostEvent) {
                HostEvent hostEvent = (HostEvent) event;

                switch (hostEvent.type()) {
                    case HOST_REMOVED:
                        log.debug("host {} was removed", hostEvent.subject().toString());
                        break;
                    default:
                        log.debug("Unsupported hostEvent type {}", hostEvent.type().toString());
                        break;
                }
            }
        }
    }

    private void readConfiguration() {
        config = configService.getConfig(appId, OpenstackSwitchingConfig.class);
        if (config == null) {
            log.error("No configuration found");
            return;
        }

        arpHandler = new OpenstackArpHandler(openstackService, packetService, hostService);
        sgRulePopulator = new OpenstackSecurityGroupRulePopulator(appId, openstackService, flowObjectiveService);

        initializeFlowRules();
    }

    private class InternalConfigListener implements NetworkConfigListener {

        @Override
        public void event(NetworkConfigEvent event) {
            if (!event.configClass().equals(OpenstackSwitchingConfig.class)) {
                return;
            }

            if (event.type().equals(NetworkConfigEvent.Type.CONFIG_ADDED) ||
                    event.type().equals(NetworkConfigEvent.Type.CONFIG_UPDATED)) {
                configEventExecutorService.execute(OpenstackSwitchingManager.this::readConfiguration);


            }
        }
    }
}
