// 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.util.List;
import java.util.Map;

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

import org.apache.log4j.Logger;

import org.apache.cloudstack.framework.config.dao.ConfigurationDao;

import com.cloud.configuration.Config;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.Vlan;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.UserIpv6AddressDao;
import com.cloud.user.Account;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;

@Local(value = {Ipv6AddressManager.class})
public class Ipv6AddressManagerImpl extends ManagerBase implements Ipv6AddressManager {
    public static final Logger s_logger = Logger.getLogger(Ipv6AddressManagerImpl.class.getName());

    String _name = null;
    int _ipv6RetryMax = 0;

    @Inject
    DataCenterDao _dcDao;
    @Inject
    VlanDao _vlanDao;
    @Inject
    NetworkModel _networkModel;
    @Inject
    UserIpv6AddressDao _ipv6Dao;
    @Inject
    NetworkDao _networkDao;
    @Inject
    ConfigurationDao _configDao;

    @Override
    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
        _name = name;
        Map<String, String> configs = _configDao.getConfiguration(params);
        _ipv6RetryMax = NumbersUtil.parseInt(configs.get(Config.NetworkIPv6SearchRetryMax.key()), 10000);
        return true;
    }

    @Override
    public UserIpv6Address assignDirectIp6Address(long dcId, Account owner, Long networkId, String requestedIp6) throws InsufficientAddressCapacityException {
        Network network = _networkDao.findById(networkId);
        if (network == null) {
            return null;
        }
        List<VlanVO> vlans = _vlanDao.listVlansByNetworkId(networkId);
        if (vlans == null) {
            s_logger.debug("Cannot find related vlan attached to network " + networkId);
            return null;
        }
        String ip = null;
        Vlan ipVlan = null;
        if (requestedIp6 == null) {
            if (!_networkModel.isIP6AddressAvailableInNetwork(networkId)) {
                throw new InsufficientAddressCapacityException("There is no more address available in the network " + network.getName(), DataCenter.class,
                    network.getDataCenterId());
            }
            for (Vlan vlan : vlans) {
                if (!_networkModel.isIP6AddressAvailableInVlan(vlan.getId())) {
                    continue;
                }
                ip = NetUtils.getIp6FromRange(vlan.getIp6Range());
                int count = 0;
                while (_ipv6Dao.findByNetworkIdAndIp(networkId, ip) != null) {
                    ip = NetUtils.getNextIp6InRange(ip, vlan.getIp6Range());
                    count++;
                    // It's an arbitrate number to prevent the infinite loop
                    if (count > _ipv6RetryMax) {
                        ip = null;
                        break;
                    }
                }
                if (ip != null) {
                    ipVlan = vlan;
                }
            }
            if (ip == null) {
                throw new InsufficientAddressCapacityException("Cannot find a usable IP in the network " + network.getName() + " after " + _ipv6RetryMax +
                    "(network.ipv6.search.retry.max) times retry!", DataCenter.class, network.getDataCenterId());
            }
        } else {
            for (Vlan vlan : vlans) {
                if (NetUtils.isIp6InRange(requestedIp6, vlan.getIp6Range())) {
                    ipVlan = vlan;
                    break;
                }
            }
            if (ipVlan == null) {
                throw new CloudRuntimeException("Requested IPv6 is not in the predefined range!");
            }
            ip = requestedIp6;
            if (_ipv6Dao.findByNetworkIdAndIp(networkId, ip) != null) {
                throw new CloudRuntimeException("The requested IP is already taken!");
            }
        }
        DataCenterVO dc = _dcDao.findById(dcId);
        Long mac = dc.getMacAddress();
        Long nextMac = mac + 1;
        dc.setMacAddress(nextMac);
        _dcDao.update(dc.getId(), dc);

        String macAddress = NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(mac));
        UserIpv6AddressVO ipVO = new UserIpv6AddressVO(ip, dcId, macAddress, ipVlan.getId());
        ipVO.setPhysicalNetworkId(network.getPhysicalNetworkId());
        ipVO.setSourceNetworkId(networkId);
        ipVO.setState(UserIpv6Address.State.Allocated);
        ipVO.setDomainId(owner.getDomainId());
        ipVO.setAccountId(owner.getAccountId());
        _ipv6Dao.persist(ipVO);
        return ipVO;
    }

    @Override
    public void revokeDirectIpv6Address(long networkId, String ip6Address) {
        UserIpv6AddressVO ip = _ipv6Dao.findByNetworkIdAndIp(networkId, ip6Address);
        if (ip != null) {
            _ipv6Dao.remove(ip.getId());
        }
    }
}
