/*
 * Copyright 2015 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.openstackswitching;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
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.onlab.packet.Ip4Prefix;
import org.onlab.packet.MacAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.dhcp.DhcpService;
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.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flowobjective.FlowObjectiveService;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;

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

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

    @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 FlowObjectiveService flowObjectiveService;

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

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

    public static final int DHCP_PORT = 67;

    private ApplicationId appId;
    private boolean doNotPushFlows;
    private OpenstackArpHandler arpHandler;

    private OpenstackSwitchingRulePopulator rulePopulator;
    private ExecutorService deviceEventExcutorService = Executors.newFixedThreadPool(10);

    private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor();
    private InternalDeviceListener internalDeviceListener = new InternalDeviceListener();
    private InternalConfigListener internalConfigListener = new InternalConfigListener();
    private final Set<ConfigFactory> factories = ImmutableSet.of(
            new ConfigFactory<ApplicationId, OpenstackSwitchingConfig>(APP_SUBJECT_FACTORY,
                    OpenstackSwitchingConfig.class,
                    "openstackswitching") {
                @Override
                public OpenstackSwitchingConfig createConfig() {
                    return new OpenstackSwitchingConfig();
                }
            }
    );
    // Map <port_id, OpenstackPort>
    private Map<String, OpenstackPort> openstackPortMap;
    // Map <network_id, OpenstackNetwork>
    private Map<String, OpenstackNetwork> openstackNetworkMap;
    // Map <subnet_id, OpenstackSubner>
    private Map<String, OpenstackSubnet> openstackSubnetMap;
    // Map <vni, List <Entry <portName, host ip>>
    private Map<String, List<PortInfo>> vniPortMap;
    private Map<Ip4Address, Port> tunnelPortMap;


    @Activate
    protected void activate() {
        appId = coreService
                .registerApplication("org.onosproject.openstackswitching");
        packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1));
        deviceService.addListener(internalDeviceListener);
        cfgService.addListener(internalConfigListener);
        factories.forEach(cfgService::registerConfigFactory);
        OpenstackSwitchingConfig cfg =
                cfgService.getConfig(appId, OpenstackSwitchingConfig.class);
        if (cfg != null) {
            doNotPushFlows = cfg.doNotPushFlows();
        }
        openstackPortMap = Maps.newHashMap();
        openstackNetworkMap = Maps.newHashMap();
        openstackSubnetMap = Maps.newHashMap();

        vniPortMap = Maps.newHashMap();
        tunnelPortMap = Maps.newHashMap();

        arpHandler = new OpenstackArpHandler(openstackPortMap, packetService);

        log.info("Started");
    }

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

        deviceEventExcutorService.shutdown();

        log.info("Stopped");
    }

    @Override
    public void createPorts(OpenstackPort openstackPort) {
        registerDhcpInfo(openstackPort);
        openstackPortMap.put(openstackPort.id(), openstackPort);
    }

    @Override
    public void deletePorts() {

    }

    @Override
    public void updatePorts() {

    }

    @Override
    public void createNetwork(OpenstackNetwork openstackNetwork) {
        openstackNetworkMap.put(openstackNetwork.id(), openstackNetwork);
    }

    @Override
    public void createSubnet(OpenstackSubnet openstackSubnet) {
        openstackSubnetMap.put(openstackSubnet.id(), openstackSubnet);
        log.debug("Added Subnet Info {}", openstackNetworkMap.get(openstackSubnet.id()));
    }

    @Override
    public Collection<OpenstackPort> ports(String networkId) {

        List<OpenstackPort> portList = openstackPortMap.values().stream()
                .filter(p -> p.networkId().equals(networkId))
                .collect(Collectors.toList());

        return portList;
    }

    @Override
    public OpenstackPort port(String portName) {
        String uuid = portName.substring(3);
        return (OpenstackPort) openstackPortMap.values().stream()
                .filter(p -> p.id().startsWith(uuid))
                .findFirst().get().clone();
    }

    @Override
    public OpenstackNetwork network(String networkId) {
        OpenstackNetwork on = null;
        try {
            on = (OpenstackNetwork) openstackNetworkMap.get(networkId).clone();
        } catch (CloneNotSupportedException e) {
            log.error("Cloning is not supported {}", e);
        }
        return on;
    }

    private void processDeviceAdded(Device device) {
        log.debug("device {} is added", device.id());
        rulePopulator.populateDefaultRules(device.id());
    }

    private void processPortAdded(Device device, Port port) {
        // TODO: Simplify the data structure to store the network info
        // TODO: Make it stateless
        // TODO: All the logics need to be processed inside of the rulePopulator class
        synchronized (vniPortMap) {
            log.debug("port {} is updated", port.toString());

            updatePortMaps(device, port);
            if (!port.annotations().value("portName").equals("vxlan")) {
                populateFlowRulesForTrafficToSameCnode(device, port);
                populateFlowRulesForTrafficToDifferentCnode(device, port);
            }
        }
    }

    private void processPortRemoved(Device device, Port port) {
        log.debug("port {} is removed", port.toString());
        // TODO: need to update the vniPortMap
    }

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

        ip4Address = (Ip4Address) openstackPort.fixedIps().values().toArray()[0];

        openstackSubnet = openstackSubnetMap.values().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("8.8.8.8");
        } else {
            domainServer = openstackSubnet.dnsNameservers().get(0);
        }
        List<Ip4Address> options = Lists.newArrayList();
        options.add(subnetMask);
        options.add(dhcpServer);
        options.add(gatewayIPAddress);
        options.add(domainServer);

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

    private byte[] buildSubnetMask(String cidr) {
        int prefix;
        String[] parts = cidr.split("/");
        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;
    }

    /**
     * Populates the flow rules for traffic to VMs in different Cnode using
     * Nicira extention.
     *
     * @param device device to put rules
     * @param port port information of the VM
     */
    private void populateFlowRulesForTrafficToDifferentCnode(Device device, Port port) {
        String portName = port.annotations().value("portName");
        String channelId = device.annotations().value("channelId");
        Ip4Address hostIpAddress = Ip4Address.valueOf(channelId.split(":")[0]);
        Ip4Address fixedIp = getFixedIpAddressForPort(portName);
        // TODO: Avoid duplicate flow rule set up for VMs in other Cnode
        //       (possibly avoided by flowrule subsystem?)
        if (tunnelPortMap.get(hostIpAddress) == null) {
            log.debug("There is no tunnel port information");
            return;
        }
        String vni = getVniForPort(portName);
        MacAddress vmMac = getVmMacAddressForPort(portName);
        if (!vniPortMap.isEmpty() && vniPortMap.get(vni) != null) {
            for (PortInfo portInfo : vniPortMap.get(vni)) {
                if (!portInfo.portName.equals(portName) &&
                        !portInfo.hostIp.equals(hostIpAddress)) {
                    MacAddress vmMacx = getVmMacAddressForPort(portInfo.portName);
                    rulePopulator.populateForwardingRuleForOtherCnode(vni,
                            device.id(), portInfo.hostIp, portInfo.fixedIp, vmMacx,
                            tunnelPortMap.get(hostIpAddress).number(),
                            portInfo.deviceId, hostIpAddress, fixedIp, vmMac,
                            tunnelPortMap.get(portInfo.hostIp).number());
                }
            }
        }
    }

    /**
     * Populates the flow rules for traffic to VMs in the same Cnode as the sender.
     *
     * @param device device to put the rules
     * @param port port info of the VM
     */
    private void populateFlowRulesForTrafficToSameCnode(Device device, Port port) {
        Ip4Prefix cidr = getCidrForPort(port.annotations().value("portName"));
        Ip4Address vmIp = getFixedIpAddressForPort(port.annotations().value("portName"));
        if (vmIp != null) {
            rulePopulator.populateForwardingRule(vmIp, device.id(), port, cidr);
        }
    }

    /**
     * Updates the port maps using the port information.
     *
     * @param device device info
     * @param port port of the VM
     */
    private void updatePortMaps(Device device, Port port) {
        String portName = port.annotations().value("portName");
        String channelId = device.annotations().value("channelId");
        Ip4Address hostIpAddress = Ip4Address.valueOf(channelId.split(":")[0]);
        if (portName.startsWith("vxlan")) {
            tunnelPortMap.put(hostIpAddress, port);
        } else {
            String vni = getVniForPort(portName);
            Ip4Address fixedIp = getFixedIpAddressForPort(portName);
            if (vniPortMap.get(vni) == null) {
                vniPortMap.put(vni, Lists.newArrayList());
            }
            vniPortMap.get(vni).add(new PortInfo(device.id(), portName, fixedIp, hostIpAddress));
        }
    }

    /**
     * Returns CIDR information from the subnet map for the port.
     *
     * @param portName port name of the port of the VM
     * @return CIDR of the VNI of the VM
     */
    private Ip4Prefix getCidrForPort(String portName) {
        String networkId = null;
        String uuid = portName.substring(3);
        OpenstackPort port = openstackPortMap.values().stream()
                .filter(p -> p.id().startsWith(uuid))
                .findFirst().get();
        if (port == null) {
            log.debug("No port information for port {}", portName);
            return null;
        }

        OpenstackSubnet subnet = openstackSubnetMap.values().stream()
                .filter(s -> s.networkId().equals(port.networkId()))
                .findFirst().get();
        if (subnet == null) {
            log.debug("No subnet information for network {}", port.networkId());
            return null;
        }

        return Ip4Prefix.valueOf(subnet.cidr());
    }

    /**
     * Returns the VNI of the VM of the port.
     *
     * @param portName VM port
     * @return VNI
     */
    private String getVniForPort(String portName) {
        String networkId = null;
        String uuid = portName.substring(3);
        OpenstackPort port = openstackPortMap.values().stream()
                .filter(p -> p.id().startsWith(uuid))
                .findFirst().get();
        if (port == null) {
            log.debug("No port information for port {}", portName);
            return null;
        }
        OpenstackNetwork network = openstackNetworkMap.values().stream()
                .filter(n -> n.id().equals(port.networkId()))
                .findFirst().get();
        if (network == null) {
            log.debug("No VNI information for network {}", network.id());
            return null;
        }

        return network.segmentId();
    }

    /**
     * Returns the Fixed IP address of the VM.
     *
     * @param portName VM port info
     * @return IP address of the VM
     */
    private Ip4Address getFixedIpAddressForPort(String portName) {

        // FIXME - For now we use the information stored from neutron Rest API call.
        // TODO - Later, the information needs to be extracted from Neutron on-demand.
        String uuid = portName.substring(3);
        OpenstackPort port = openstackPortMap.values().stream()
                        .filter(p -> p.id().startsWith(uuid))
                        .findFirst().get();

        if (port == null) {
            log.error("There is no port information for port name {}", portName);
            return null;
        }

        if (port.fixedIps().isEmpty()) {
            log.error("There is no fixed IP info in the port information");
            return null;
        }

        return (Ip4Address) port.fixedIps().values().toArray()[0];
    }

    /**
     * Returns the MAC address of the VM of the port.
     *
     * @param portName VM port
     * @return MAC address of the VM
     */
    private MacAddress getVmMacAddressForPort(String portName) {

        String uuid = portName.substring(3);
        OpenstackPort port = openstackPortMap.values().stream()
                .filter(p -> p.id().startsWith(uuid))
                .findFirst().get();

        if (port == null) {
            log.error("There is no mac information for port name {}", portName);
            return null;
        }

        return port.macAddress();
    }

    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.getEtherType() == Ethernet.TYPE_ARP) {
                arpHandler.processPacketIn(pkt);
            }
        }
    }

    private class InternalDeviceListener implements DeviceListener {

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

    private class InternalEventHandler implements Runnable {

        volatile DeviceEvent deviceEvent;

        InternalEventHandler(DeviceEvent deviceEvent) {
            this.deviceEvent = deviceEvent;
        }

        @Override
        public void run() {

            if (doNotPushFlows) {
                return;
            }

            switch (deviceEvent.type()) {
                case DEVICE_ADDED:
                    processDeviceAdded((Device) deviceEvent.subject());
                    break;
                case DEVICE_UPDATED:
                    Port port = (Port) deviceEvent.subject();
                    if (port.isEnabled()) {
                        processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
                    }
                    break;
                case DEVICE_AVAILABILITY_CHANGED:
                    Device device = (Device) deviceEvent.subject();
                    if (deviceService.isAvailable(device.id())) {
                        processDeviceAdded(device);
                    }
                    break;
                case PORT_ADDED:
                    processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
                    break;
                case PORT_UPDATED:
                    processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
                    break;
                case PORT_REMOVED:
                    processPortRemoved((Device) deviceEvent.subject(), deviceEvent.port());
                    break;
                default:
                    break;
            }
        }
    }

    private class InternalConfigListener implements NetworkConfigListener {

        @Override
        public void event(NetworkConfigEvent event) {
            if (((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
            event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)) &&
                    event.configClass().equals(OpenstackSwitchingConfig.class)) {
                OpenstackSwitchingConfig cfg = cfgService.getConfig(appId,
                        OpenstackSwitchingConfig.class);
                if (cfg != null) {
                    doNotPushFlows = cfg.doNotPushFlows();
                    log.info("Switching mode reconfigured");
                }
            }
        }
   }

    private final class PortInfo {
        DeviceId deviceId;
        String portName;
        Ip4Address fixedIp;
        Ip4Address hostIp;

        private PortInfo(DeviceId deviceId, String portName, Ip4Address fixedIp,
                         Ip4Address hostIp) {
            this.deviceId = deviceId;
            this.portName = portName;
            this.fixedIp = fixedIp;
            this.hostIp = hostIp;
        }
    }

}