// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 com.cloud.network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;

import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;

import org.apache.log4j.Logger;

import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.exception.CloudRuntimeException;

@Local(value=IpAddrAllocator.class)
public class ExternalIpAddressAllocator extends AdapterBase implements IpAddrAllocator{
    private static final Logger s_logger = Logger.getLogger(ExternalIpAddressAllocator.class);
    String _name;
    @Inject ConfigurationDao _configDao = null;
    @Inject IPAddressDao _ipAddressDao = null;
    @Inject VlanDao _vlanDao;
    private boolean _isExternalIpAllocatorEnabled = false;
    private String _externalIpAllocatorUrl = null;


    @Override
    public IpAddr getPrivateIpAddress(String macAddr, long dcId, long podId) {
        if (_externalIpAllocatorUrl == null || this._externalIpAllocatorUrl.equalsIgnoreCase("")) {
            return new IpAddr();
        }
        String urlString = this._externalIpAllocatorUrl + "?command=getIpAddr&mac=" + macAddr + "&dc=" + dcId + "&pod=" + podId;
        s_logger.debug("getIP:" + urlString);

        BufferedReader in = null;
        try {
            URL url = new URL(urlString);
            URLConnection conn = url.openConnection();
            conn.setReadTimeout(30000);

            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                s_logger.debug(inputLine);
                String[] tokens = inputLine.split(",");
                if (tokens.length != 3) {
                    s_logger.debug("the return value should be: mac,netmask,gateway");
                    return new IpAddr();
                }
                return new IpAddr(tokens[0], tokens[1], tokens[2]);
            }

            return new IpAddr();
        } catch (MalformedURLException e) {
            throw new CloudRuntimeException("URL is malformed " + urlString, e);
        } catch (IOException e) {
            return new IpAddr();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                }
            }
        }

    }

    @Override
    public IpAddr getPublicIpAddress(String macAddr, long dcId, long podId) {
        /*TODO: call API to get  ip address from external DHCP server*/
        return getPrivateIpAddress(macAddr, dcId, podId);
    }

    @Override
    public boolean releasePrivateIpAddress(String ip, long dcId, long podId) {
        /*TODO: call API to release the ip address from external DHCP server*/
        if (_externalIpAllocatorUrl == null || this._externalIpAllocatorUrl.equalsIgnoreCase("")) {
            return false;
        }

        String urlString = this._externalIpAllocatorUrl + "?command=releaseIpAddr&ip=" + ip + "&dc=" + dcId + "&pod=" + podId;

        s_logger.debug("releaseIP:" + urlString);
        BufferedReader in = null;
        try {
            URL url = new URL(urlString);
            URLConnection conn = url.openConnection();
            conn.setReadTimeout(30000);

            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));

            return true;
        } catch (MalformedURLException e) {
            throw new CloudRuntimeException("URL is malformed " + urlString, e);
        } catch (IOException e) {
            return false;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                }
            }
        }
    }

    @Override
    public boolean releasePublicIpAddress(String ip, long dcId, long podId) {
        /*TODO: call API to release the ip address from external DHCP server*/
        return releasePrivateIpAddress(ip, dcId, podId);
    }

    @Override
    public boolean externalIpAddressAllocatorEnabled() {
        return _isExternalIpAllocatorEnabled;
    }

    @Override
    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
        _isExternalIpAllocatorEnabled = Boolean.parseBoolean(_configDao.getValue("direct.attach.network.externalIpAllocator.enabled"));
        _externalIpAllocatorUrl = _configDao.getValue("direct.attach.network.externalIpAllocator.url");
        _name = name;

        return true;
    }

    @Override
    public String getName() {
        return _name;
    }

    @Override
    public boolean start() {
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }
}
