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

import com.cloud.dc.ASNumberRangeVO;
import com.cloud.dc.ASNumberVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.ASNumberDao;
import com.cloud.dc.dao.ASNumberRangeDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.domain.Domain;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
import com.cloud.network.NetworkModel;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkServiceMapDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.element.BgpServiceProvider;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcOfferingVO;
import com.cloud.network.vpc.VpcVO;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.network.vpc.dao.VpcOfferingDao;
import com.cloud.network.vpc.dao.VpcServiceMapDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
import com.cloud.user.Account;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.Pair;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallback;
import com.cloud.utils.db.TransactionCallbackNoReturn;
import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.command.user.bgp.ListASNumbersCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.network.BgpPeer;
import org.apache.cloudstack.network.BgpPeerVO;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.network.dao.BgpPeerDao;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.inject.Inject;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class BGPServiceImpl implements BGPService {

    public static final Logger LOGGER = LogManager.getLogger(BGPServiceImpl.class);

    @Inject
    private DataCenterDao dataCenterDao;
    @Inject
    private ASNumberRangeDao asNumberRangeDao;
    @Inject
    private ASNumberDao asNumberDao;
    @Inject
    private NetworkDao networkDao;
    @Inject
    private VpcDao vpcDao;
    @Inject
    private VpcOfferingDao vpcOfferingDao;
    @Inject
    private NetworkOfferingDao networkOfferingDao;
    @Inject
    private AccountDao accountDao;
    @Inject
    private DomainDao domainDao;
    @Inject
    NetworkServiceMapDao ntwkSrvcDao;
    @Inject
    NetworkModel networkModel;
    @Inject
    BgpPeerDao bgpPeerDao;
    @Inject
    RoutedIpv4Manager routedIpv4Manager;
    @Inject
    VpcServiceMapDao vpcServiceMapDao;

    public BGPServiceImpl() {
    }

    @Override
    @DB
    @ActionEvent(eventType = EventTypes.EVENT_AS_RANGE_CREATE, eventDescription = "AS Range creation")
    public ASNumberRange createASNumberRange(long zoneId, long startASNumber, long endASNumber) {
        DataCenterVO zone = dataCenterDao.findById(zoneId);
        if (zone == null) {
            String msg = String.format("Cannot find a zone with ID %s", zoneId);
            LOGGER.error(msg);
            throw new InvalidParameterException(msg);
        }
        if (!routedIpv4Manager.isRoutedNetworkVpcEnabled(zoneId)) {
            throw new InvalidParameterValueException("Cannot create ASN range as Routed networks and VPCs are not enabled for the zone.");
        }
        if (startASNumber > endASNumber) {
            String msg = "Please specify a valid AS Number range";
            LOGGER.error(msg);
            throw new InvalidParameterException(msg);
        }

        List<ASNumberRangeVO> asNumberRanges = asNumberRangeDao.listByZoneId(zoneId);
        for (ASNumberRangeVO asNumberRange : asNumberRanges) {
            if (isASNumbersOverlap(asNumberRange.getStartASNumber(), asNumberRange.getEndASNumber(), startASNumber, endASNumber)) {
                throw new InvalidParameterException(String.format("New AS number range (%s-%s) has conflict with an existing AS number range (%s-%s)",
                        startASNumber, endASNumber, asNumberRange.getStartASNumber(), asNumberRange.getEndASNumber()));
            }
        }

        try {
            return Transaction.execute((TransactionCallback<ASNumberRange>) status -> {
                LOGGER.debug("Persisting AS Number Range {}-{} for the zone {}", startASNumber, endASNumber, zone);
                ASNumberRangeVO asNumberRangeVO = new ASNumberRangeVO(zoneId, startASNumber, endASNumber);
                asNumberRangeDao.persist(asNumberRangeVO);

                for (long asn = startASNumber; asn <= endASNumber; asn++) {
                    LOGGER.debug("Persisting AS Number {} for zone {}", asn, zone);
                    ASNumberVO asNumber = new ASNumberVO(asn, asNumberRangeVO.getId(), zoneId);
                    asNumberDao.persist(asNumber);
                }
                return asNumberRangeVO;
            });
        } catch (Exception e) {
            String err = String.format("Error creating AS Number range %s-%s for zone %s: %s", startASNumber, endASNumber, zone, e.getMessage());
            LOGGER.error(err, e);
            throw new CloudRuntimeException(err);
        }
    }

    protected boolean isASNumbersOverlap(long startNumber1, long endNumber1, long startNumber2, long endNumber2) {
        if (startNumber1 > endNumber2 || startNumber2 > endNumber1) {
            return false;
        }
        return true;
    }

    @Override
    public List<ASNumberRange> listASNumberRanges(Long zoneId) {
        List<ASNumberRangeVO> rangeVOList = zoneId != null ? asNumberRangeDao.listByZoneId(zoneId) : asNumberRangeDao.listAll();
        return new ArrayList<>(rangeVOList);
    }

    @Override
    public Pair<List<ASNumber>, Integer> listASNumbers(ListASNumbersCmd cmd) {
        Long zoneId = cmd.getZoneId();
        Long asNumberRangeId = cmd.getAsNumberRangeId();
        Integer asNumber = cmd.getAsNumber();
        Boolean allocated = cmd.getAllocated();
        Long networkId = cmd.getNetworkId();
        Long vpcId = cmd.getVpcId();
        String accountName = cmd.getAccount();
        Long domainId = cmd.getDomainId();
        Long startIndex = cmd.getStartIndex();
        Long pageSizeVal = cmd.getPageSizeVal();
        String keyword = cmd.getKeyword();

        Account userAccount = null;
        Domain domain = null;
        final Account caller = CallContext.current().getCallingAccount();
        if (Objects.nonNull(accountName)) {
            if (domainId != null) {
                userAccount = accountDao.findActiveAccount(accountName, domainId);
                domain = domainDao.findById(domainId);
            } else {
                userAccount = accountDao.findActiveAccount(accountName, caller.getDomainId());
                domain = domainDao.findById(caller.getDomainId());
            }
        }

        if (Objects.nonNull(accountName) && Objects.isNull(userAccount)) {
            throw new InvalidParameterException(String.format("Failed to find user Account: %s", accountName));
        }

        Long networkSearchId = networkId;
        Long vpcSerchId = vpcId;
        if (networkId != null) {
            NetworkVO network = networkDao.findById(networkId);
            if (network == null) {
                throw new InvalidParameterException(String.format("Failed to find network with ID: %s", networkId));
            }
            if (network.getVpcId() != null) {
                LOGGER.debug("The network {} is a VPC tier, searching for the AS number on the VPC {}",
                        network::toString, () -> vpcDao.findById(network.getVpcId()));
                networkSearchId = null;
                vpcSerchId = network.getVpcId();
            }
        }
        Pair<List<ASNumberVO>, Integer> pair = asNumberDao.searchAndCountByZoneOrRangeOrAllocated(zoneId, asNumberRangeId,
                asNumber, networkSearchId, vpcSerchId, allocated, Objects.nonNull(userAccount) ? userAccount.getId() : null,
                Objects.nonNull(domain) ? domain.getId() : null, keyword, caller, startIndex, pageSizeVal);
        return new Pair<>(new ArrayList<>(pair.first()), pair.second());
    }

    @Override
    public boolean allocateASNumber(long zoneId, Long asNumber, Long networkId, Long vpcId) {
        ASNumberVO asNumberVO = isOfferingSpecifyAsNumber(networkId, vpcId) ?
                asNumberDao.findByAsNumber(asNumber) :
                asNumberDao.findOneByAllocationStateAndZone(zoneId, false);
        if (asNumberVO == null || asNumberVO.getDataCenterId() != zoneId) {
            if (asNumber != null) {
                LOGGER.error("Cannot find AS number {} in zone {} with id {}", asNumber, dataCenterDao.findById(zoneId), zoneId);
                return false;
            }
            throw new CloudRuntimeException(String.format("Cannot allocate AS number in zone with ID %s", zoneId));
        }
        long accountId, domainId;
        String netName;
        VpcVO vpc = null;
        NetworkVO network = null;
        if (Objects.nonNull(vpcId)) {
            vpc = vpcDao.findById(vpcId);
            if (vpc == null) {
                LOGGER.error(String.format("Cannot find VPC with ID %s", vpcId));
                return false;
            }
            accountId = vpc.getAccountId();
            domainId = vpc.getDomainId();
            netName = vpc.getName();
        } else {
            network = networkDao.findById(networkId);
            if (network == null) {
                LOGGER.error(String.format("Cannot find network with ID %s", networkId));
                return false;
            }
            accountId = network.getAccountId();
            domainId = network.getDomainId();
            netName = network.getName();
        }

        String networkName = Objects.nonNull(vpcId) ? ("VPC " + vpc) : ("network " + network);
        LOGGER.debug("Allocating the AS Number {} to {} on zone {}", asNumberVO::toString,
                networkName::toString, () -> dataCenterDao.findById(zoneId));
        asNumberVO.setAllocated(true);
        asNumberVO.setAllocatedTime(new Date());
        if (Objects.nonNull(vpcId)) {
            asNumberVO.setVpcId(vpcId);
        } else {
            asNumberVO.setNetworkId(networkId);
        }
        asNumberVO.setAccountId(accountId);
        asNumberVO.setDomainId(domainId);
        return asNumberDao.update(asNumberVO.getId(), asNumberVO);
    }

    private boolean isOfferingSpecifyAsNumber(Long networkId, Long vpcId) {
        if (Objects.nonNull(vpcId)) {
            VpcVO vpc = vpcDao.findById(vpcId);
            if (vpc == null) {
                throw new CloudRuntimeException(String.format("Cannot find VPC with ID %s", vpcId));
            }
            VpcOfferingVO vpcOffering = vpcOfferingDao.findById(vpc.getVpcOfferingId());
            return NetworkOffering.RoutingMode.Dynamic == vpcOffering.getRoutingMode() && BooleanUtils.toBoolean(vpcOffering.isSpecifyAsNumber());
        } else {
            NetworkVO network = networkDao.findById(networkId);
            NetworkOfferingVO networkOffering = networkOfferingDao.findById(network.getNetworkOfferingId());
            return NetworkOffering.RoutingMode.Dynamic == networkOffering.getRoutingMode() && BooleanUtils.toBoolean(networkOffering.isSpecifyAsNumber());
        }
    }

    private Pair<Boolean, String> logAndReturnErrorMessage(String msg) {
        LOGGER.error(msg);
        return new Pair<>(false, msg);
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_AS_NUMBER_RELEASE, eventDescription = "Releasing AS Number")
    public Pair<Boolean, String> releaseASNumber(long zoneId, long asNumber, boolean isDestroyNetworkOperation) {
        ASNumberVO asNumberVO = asNumberDao.findByAsNumber(asNumber);
        DataCenterVO zone = dataCenterDao.findById(zoneId);
        if (asNumberVO == null) {
            return logAndReturnErrorMessage(String.format("Cannot find AS Number %s on zone %s", asNumber, zone));
        }
        if (!asNumberVO.isAllocated()) {
            LOGGER.debug("The AS Number {} is not allocated to any network on zone {}, ignoring release", asNumber, zone);
            return new Pair<>(true, "");
        }
        Long networkId = asNumberVO.getNetworkId();
        Long vpcId = asNumberVO.getVpcId();
        if (!isDestroyNetworkOperation) {
            Pair<Boolean, String> checksResult = performReleaseASNumberChecks(networkId, vpcId, asNumber);
            if (checksResult != null) {
                return checksResult;
            }
        }
        LOGGER.debug("Releasing AS Number {} on zone {} from previous allocation", asNumber, zone);
        asNumberVO.setAllocated(false);
        asNumberVO.setAllocatedTime(null);
        asNumberVO.setDomainId(null);
        asNumberVO.setAccountId(null);
        if (vpcId != null) {
            asNumberVO.setVpcId(null);
        } else {
            asNumberVO.setNetworkId(null);
        }
        boolean update = asNumberDao.update(asNumberVO.getId(), asNumberVO);
        String msg = update ? "OK" : "Could not update database record for AS number";
        return new Pair<>(update, msg);
    }

    private Pair<Boolean, String> performReleaseASNumberChecks(Long networkId, Long vpcId, long asNumber) {
        if (networkId != null) {
            NetworkVO network = networkDao.findById(networkId);
            if (network == null) {
                return logAndReturnErrorMessage(String.format("Cannot find a network with ID %s which acquired the AS number %s", networkId, asNumber));
            }
            NetworkOfferingVO offering = networkOfferingDao.findById(network.getNetworkOfferingId());
            if (offering == null) {
                return logAndReturnErrorMessage(String.format("Cannot find a network offering with ID %s", network.getNetworkOfferingId()));
            }
            if (offering.isSpecifyAsNumber()) {
                return logAndReturnErrorMessage(String.format("Cannot release the AS number %s as it is acquired by a network that requires AS number", asNumber));
            }
        } else if (vpcId != null) {
            VpcVO vpc = vpcDao.findById(vpcId);
            if (vpc == null) {
                return logAndReturnErrorMessage(String.format("Cannot find a VPC with ID %s which acquired the AS number %s", vpcId, asNumber));
            }
            VpcOfferingVO vpcOffering = vpcOfferingDao.findById(vpc.getVpcOfferingId());
            if (vpcOffering == null) {
                return logAndReturnErrorMessage(String.format("Cannot find a VPC offering with ID %s", vpc.getVpcOfferingId()));
            }
            if (vpcOffering.isSpecifyAsNumber()) {
                return logAndReturnErrorMessage(String.format("Cannot release the AS number %s as it is acquired by a VPC that requires AS number", asNumber));
            }
        }
        return null;
    }

    @Override
    @DB
    @ActionEvent(eventType = EventTypes.EVENT_AS_RANGE_DELETE, eventDescription = "Deleting AS Range")
    public boolean deleteASRange(long id) {
        final ASNumberRange asRange = asNumberRangeDao.findById(id);
        if (asRange == null) {
            throw new CloudRuntimeException(String.format("Could not find a AS range with id: %s", id));
        }
        long startASNumber = asRange.getStartASNumber();
        long endASNumber = asRange.getEndASNumber();
        long zoneId = asRange.getDataCenterId();
        DataCenterVO zone = dataCenterDao.findById(zoneId);
        List<ASNumberVO> allocatedAsNumbers = asNumberDao.listAllocatedByASRange(asRange.getId());
        if (Objects.nonNull(allocatedAsNumbers) && !allocatedAsNumbers.isEmpty()) {
            throw new CloudRuntimeException(String.format("There are %s AS numbers in use from the range %s-%s, cannot remove the range",
                    allocatedAsNumbers.size(), startASNumber, endASNumber));
        }
        try {
            Transaction.execute(new TransactionCallbackNoReturn() {
                @Override
                public void doInTransactionWithoutResult(TransactionStatus status) {
                    int removedASNumbers = asNumberDao.removeASRangeNumbers(asRange.getId());
                    LOGGER.debug(String.format("Removed %s AS numbers from the range %s-%s", removedASNumbers,
                            startASNumber, endASNumber));
                    asNumberRangeDao.remove(id);
                    LOGGER.debug("Removing the AS Number Range {}-{} for the zone {}", startASNumber, endASNumber, zone);
                }
            });
        } catch (Exception e) {
            String err = String.format("Error removing AS Number range %s-%s for zone %s: %s",
                    startASNumber, endASNumber, zone, e.getMessage());
            LOGGER.error(err, e);
            throw new CloudRuntimeException(err);
        }
        return true;
    }

    @Override
    public boolean applyBgpPeers(Network network, boolean continueOnError) throws ResourceUnavailableException {
        if (!routedIpv4Manager.isDynamicRoutedNetwork(network)) {
            return true;
        }
        final String gatewayProviderStr = ntwkSrvcDao.getProviderForServiceInNetwork(network.getId(), Network.Service.Gateway);
        if (gatewayProviderStr != null) {
            NetworkElement provider = networkModel.getElementImplementingProvider(gatewayProviderStr);
            if (provider != null && provider instanceof BgpServiceProvider) {
                List<? extends BgpPeer> bgpPeers = getBgpPeersForNetwork(network);
                LOGGER.debug(String.format("Applying BPG Peers for network [%s]: [%s]", network, bgpPeers));
                return ((BgpServiceProvider) provider).applyBgpPeers(null, network, bgpPeers);
            }
        }
        return true;
    }

    @Override
    public boolean applyBgpPeers(Vpc vpc, boolean continueOnError) throws ResourceUnavailableException {
        if (!routedIpv4Manager.isDynamicRoutedVpc(vpc)) {
            return true;
        }
        final String gatewayProviderStr = vpcServiceMapDao.getProviderForServiceInVpc(vpc.getId(), Network.Service.Gateway);
        if (gatewayProviderStr != null) {
            NetworkElement provider = networkModel.getElementImplementingProvider(gatewayProviderStr);
            if (provider != null && provider instanceof BgpServiceProvider) {
                List<? extends BgpPeer> bgpPeers = getBgpPeersForVpc(vpc);
                LOGGER.debug(String.format("Applying BPG Peers for VPC [%s]: [%s]", vpc, bgpPeers));
                return ((BgpServiceProvider) provider).applyBgpPeers(vpc, null, bgpPeers);

            }
        }
        return true;
    }

    @Override
    public List<? extends BgpPeer> getBgpPeersForNetwork(Network network) {
        List<BgpPeerVO> bgpPeers;
        if (network.getVpcId() != null) {
            bgpPeers = bgpPeerDao.listNonRevokeByVpcId(network.getVpcId());
        } else {
            bgpPeers = bgpPeerDao.listNonRevokeByNetworkId(network.getId());
        }
        if (CollectionUtils.isEmpty(bgpPeers)) {
            Account owner = accountDao.findByIdIncludingRemoved(network.getAccountId());
            List<Long> bgpPeerIds = routedIpv4Manager.getBgpPeerIdsForAccount(owner, network.getDataCenterId());
            bgpPeers = bgpPeerIds.stream()
                    .map(bgpPeerId -> bgpPeerDao.findById(bgpPeerId))
                    .collect(Collectors.toList());
        }
        return bgpPeers;
    }

    @Override
    public List<? extends BgpPeer> getBgpPeersForVpc(Vpc vpc) {
        List<BgpPeerVO> bgpPeers = bgpPeerDao.listNonRevokeByVpcId(vpc.getId());
        if (CollectionUtils.isEmpty(bgpPeers)) {
            Account owner = accountDao.findByIdIncludingRemoved(vpc.getAccountId());
            List<Long> bgpPeerIds = routedIpv4Manager.getBgpPeerIdsForAccount(owner, vpc.getZoneId());
            bgpPeers = bgpPeerIds.stream()
                    .map(bgpPeerId -> bgpPeerDao.findById(bgpPeerId))
                    .collect(Collectors.toList());
        }
        return bgpPeers;
    }
}
