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

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());
        }
    }
}
