/*
 * 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.virtualbng;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

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.Service;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implementation of ConfigurationService which reads virtual BNG
 * configuration from a file.
 */
@Component(immediate = true)
@Service
public class VbngConfigurationManager implements VbngConfigurationService {

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

    private static final String CONFIG_DIR = "../config";
    private static final String DEFAULT_CONFIG_FILE = "virtualbng.json";
    private String configFileName = DEFAULT_CONFIG_FILE;

    // If all the IP addresses of one IP prefix are assigned, then we
    // mark the value of this IP prefix as false, otherwise as true.
    private Map<IpPrefix, Boolean> localPublicIpPrefixes =
            new ConcurrentHashMap<>();

    // Map from private IP address to public IP address
    private Map<IpAddress, IpAddress> ipAddressMap =
            new ConcurrentHashMap<>();

    private IpAddress nextHopIpAddress;
    private MacAddress macOfPublicIpAddresses;
    private IpAddress xosIpAddress;
    private int xosRestPort;

    @Activate
    public void activate() {
        readConfiguration();
        log.info("vBNG configuration service started");
    }

    @Deactivate
    public void deactivate() {
        log.info("vBNG configuration service stopped");
    }

    /**
     * Instructs the configuration reader to read the configuration from the
     * file.
     */
    public void readConfiguration() {
        readConfiguration(configFileName);
    }

    /**
     * Reads virtual BNG information contained in configuration file.
     *
     * @param configFilename the name of the configuration file for the virtual
     * BNG application
     */
    private void readConfiguration(String configFilename) {
        File configFile = new File(CONFIG_DIR, configFilename);
        ObjectMapper mapper = new ObjectMapper();

        try {
            log.info("Loading config: {}", configFile.getAbsolutePath());
            VbngConfiguration config = mapper.readValue(configFile,
                                                    VbngConfiguration.class);
            for (IpPrefix prefix : config.getLocalPublicIpPrefixes()) {
                localPublicIpPrefixes.put(prefix, true);
            }
            nextHopIpAddress = config.getNextHopIpAddress();
            macOfPublicIpAddresses = config.getPublicFacingMac();
            xosIpAddress = config.getXosIpAddress();
            xosRestPort = config.getXosRestPort();

        } catch (FileNotFoundException e) {
            log.warn("Configuration file not found: {}", configFileName);
        } catch (IOException e) {
            log.error("Error loading configuration", e);
        }
    }

    @Override
    public IpAddress getNextHopIpAddress() {
        return nextHopIpAddress;
    }

    @Override
    public MacAddress getPublicFacingMac() {
        return macOfPublicIpAddresses;
    }

    @Override
    public IpAddress getXosIpAddress() {
        return xosIpAddress;
    }

    @Override
    public int getXosRestPort() {
        return xosRestPort;
    }

    // TODO handle the case: the number of public IP addresses is not enough
    // for 1:1 mapping from public IP to private IP.
    @Override
    public synchronized IpAddress getAvailablePublicIpAddress(IpAddress
                                                           privateIpAddress) {
        // If there is already a mapping entry for the private IP address,
        // then fetch the public IP address in the mapping entry and return it.
        IpAddress publicIpAddress = ipAddressMap.get(privateIpAddress);
        if (publicIpAddress != null) {
            return publicIpAddress;
        }
        // There is no mapping for the private IP address.
        Iterator<Entry<IpPrefix, Boolean>> prefixes =
                localPublicIpPrefixes.entrySet().iterator();
        while (prefixes.hasNext()) {
            Entry<IpPrefix, Boolean> prefix = prefixes.next();
            if (!prefix.getValue()) {
                continue;
            }

            if (prefix.getKey().prefixLength() == 32) {
                updateIpPrefixStatus(prefix.getKey(), false);
                publicIpAddress = prefix.getKey().address();
                ipAddressMap.put(privateIpAddress, publicIpAddress);
                return publicIpAddress;
            }

            int prefixLen = prefix.getKey().prefixLength();
            int availableIpNum = (int) Math.pow(2,
                    IpPrefix.MAX_INET_MASK_LENGTH - prefixLen) - 1;
            for (int i = 1; i <= availableIpNum; i++) {
                publicIpAddress =
                        increaseIpAddress(prefix.getKey().address(), i);
                if (publicIpAddress == null) {
                    return null;
                }
                if (ipAddressMap.values().contains(publicIpAddress)) {
                    continue;
                } else if (i == availableIpNum) {
                    // All the IP addresses are assigned out
                    // Update this IP prefix status to false
                    // Note: in this version we do not consider the
                    // IP recycling issue.
                    updateIpPrefixStatus(prefix.getKey(), false);
                    ipAddressMap.put(privateIpAddress, publicIpAddress);
                    return publicIpAddress;
                } else {
                    ipAddressMap.put(privateIpAddress, publicIpAddress);
                    return publicIpAddress;
                }
            }
        }
        return null;
    }

    @Override
    public IpAddress getAssignedPublicIpAddress(IpAddress privateIpAddress) {
        return ipAddressMap.get(privateIpAddress);
    }

    @Override
    public boolean isAssignedPublicIpAddress(IpAddress ipAddress) {
        return ipAddressMap.containsValue(ipAddress);
    }

    @Override
    public synchronized IpAddress recycleAssignedPublicIpAddress(IpAddress
                                                    privateIpAddress) {
        IpAddress publicIpAddress = ipAddressMap.remove(privateIpAddress);
        if (publicIpAddress == null) {
            return null;
        }

        Iterator<Entry<IpPrefix, Boolean>> prefixes =
                localPublicIpPrefixes.entrySet().iterator();
        while (prefixes.hasNext()) {
            Entry<IpPrefix, Boolean> prefixEntry = prefixes.next();
            if (prefixEntry.getKey().contains(publicIpAddress)
                    && !prefixEntry.getValue()) {
                updateIpPrefixStatus(prefixEntry.getKey(), true);
            }
        }
        log.info("[DELETE] Private IP to Public IP mapping: {} --> {}",
                 privateIpAddress, publicIpAddress);
        return publicIpAddress;
    }

    @Override
    public Map<IpAddress, IpAddress> getIpAddressMappings() {
        return Collections.unmodifiableMap(ipAddressMap);
    }

    @Override
    public synchronized boolean assignSpecifiedPublicIp(IpAddress publicIpAddress,
                                  IpAddress privateIpAddress) {

        // Judge whether this public IP address is in our public IP
        // prefix/address list.
        boolean isPublicIpExist = false;
        for (Entry<IpPrefix, Boolean> prefix: localPublicIpPrefixes.entrySet()) {
            if (prefix.getKey().contains(publicIpAddress)) {
                isPublicIpExist = true;

                // Judge whether this public IP address is already assigned
                if (!prefix.getValue() ||
                        isAssignedPublicIpAddress(publicIpAddress)) {
                    log.info("The public IP address {} is already assigned, "
                            + "and not available.", publicIpAddress);
                    return false;
                }

                // The public IP address is still available
                // Store the mapping from private IP address to public IP address
                ipAddressMap.put(privateIpAddress, publicIpAddress);

                // Update the prefix status
                if (prefix.getKey().prefixLength() == 32) {
                    updateIpPrefixStatus(prefix.getKey(), false);
                    return true;
                }

                // Judge whether the prefix of this public IP address is used
                // up, if so, update the IP prefix status.
                int prefixLen = prefix.getKey().prefixLength();
                int availableIpNum = (int) Math.pow(2,
                        IpPrefix.MAX_INET_MASK_LENGTH - prefixLen) - 1;
                int usedIpNum = 0;
                for (Entry<IpAddress, IpAddress> ipAddressMapEntry:
                    ipAddressMap.entrySet()) {
                    if (prefix.getKey().contains(ipAddressMapEntry.getValue())) {
                        usedIpNum = usedIpNum + 1;
                    }
                }
                if (usedIpNum == availableIpNum) {
                    updateIpPrefixStatus(prefix.getKey(), false);
                }

                return true;
            }
        }
        if (!isPublicIpExist) {
            log.info("The public IP address {} retrieved from XOS mapping does "
                    + "not exist", publicIpAddress);
        }
        return false;
    }

    /**
     * Generates a new IP address base on a given IP address plus a number to
     * increase.
     *
     * @param ipAddress the IP address to increase
     * @param num the number for ipAddress to add
     * @return the new IP address after increase
     */
    private IpAddress increaseIpAddress(IpAddress ipAddress, int num) {
        if (ipAddress.isIp6()) {
            log.info("vBNG currently does not handle IPv6");
            return null;
        }
        return IpAddress.valueOf(ipAddress.getIp4Address().toInt() + num);
    }

    /**
     * Updates the IP prefix status in the local public IP prefix table.
     *
     * @param ipPprefix the IP prefix to update
     * @param b the new value for the IP prefix
     */
    private void updateIpPrefixStatus(IpPrefix ipPprefix, boolean b) {
            localPublicIpPrefixes.replace(ipPprefix, b);
    }

}
