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

import org.apache.cloudstack.network.topology.NetworkTopologyVisitor;
import org.apache.log4j.Logger;

import com.cloud.exception.ConcurrentOperationException;
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.router.NetworkHelper;
import com.cloud.network.router.NicProfileHelper;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.vpc.NetworkACLManager;
import com.cloud.network.vpc.PrivateGateway;
import com.cloud.network.vpc.PrivateIpVO;
import com.cloud.vm.NicProfile;
import com.cloud.vm.VirtualMachineManager;

public class PrivateGatewayRules extends RuleApplier {

    private static final Logger s_logger = Logger.getLogger(PrivateGatewayRules.class);

    private final PrivateGateway _privateGateway;

    private boolean _isAddOperation;
    private NicProfile _nicProfile;

    public PrivateGatewayRules(final PrivateGateway privateGateway) {
        super(null);
        _privateGateway = privateGateway;
    }

    @Override
    public boolean accept(final NetworkTopologyVisitor visitor, final VirtualRouter router) throws ResourceUnavailableException {
        _router = router;

        boolean result = false;
        try {
            final NetworkModel networkModel = visitor.getVirtualNetworkApplianceFactory().getNetworkModel();
            _network = networkModel.getNetwork(_privateGateway.getNetworkId());

            final NicProfileHelper nicProfileHelper = visitor.getVirtualNetworkApplianceFactory().getNicProfileHelper();
            final NicProfile requested = nicProfileHelper.createPrivateNicProfileForGateway(_privateGateway, _router);

            final NetworkHelper networkHelper = visitor.getVirtualNetworkApplianceFactory().getNetworkHelper();
            if (!networkHelper.checkRouterVersion(_router)) {
                s_logger.warn("Router requires upgrade. Unable to send command to router: " + _router.getId());
                return false;
            }
            final VirtualMachineManager itMgr = visitor.getVirtualNetworkApplianceFactory().getItMgr();
            _nicProfile = itMgr.addVmToNetwork(_router, _network, requested);

            // setup source nat
            if (_nicProfile != null) {
                _isAddOperation = true;
                // result = setupVpcPrivateNetwork(router, true, guestNic);
                result = visitor.visit(this);
            }
        } catch (final Exception ex) {
            s_logger.warn("Failed to create private gateway " + _privateGateway + " on router " + _router + " due to ", ex);
        } finally {
            if (!result) {
                s_logger.debug("Failed to setup gateway " + _privateGateway + " on router " + _router + " with the source nat. Will now remove the gateway.");
                _isAddOperation = false;
                final boolean isRemoved = destroyPrivateGateway(visitor);

                if (isRemoved) {
                    s_logger.debug("Removed the gateway " + _privateGateway + " from router " + _router + " as a part of cleanup");
                } else {
                    s_logger.warn("Failed to remove the gateway " + _privateGateway + " from router " + _router + " as a part of cleanup");
                }
            }
        }
        return result;
    }

    public boolean isAddOperation() {
        return _isAddOperation;
    }

    public NicProfile getNicProfile() {
        return _nicProfile;
    }

    public PrivateIpVO retrivePrivateIP(final NetworkTopologyVisitor visitor) {
        final PrivateIpVO ipVO = visitor.getVirtualNetworkApplianceFactory().getPrivateIpDao().findByIpAndSourceNetworkId(_nicProfile.getNetworkId(), _nicProfile.getIPv4Address());
        return ipVO;
    }

    public Network retrievePrivateNetwork(final NetworkTopologyVisitor visitor) {
        // This network might be the same we have already as an instance in the
        // RuleApplier super class.
        // Just doing this here, but will double check is remove if it's not
        // needed.
        final NetworkDao networkDao = visitor.getVirtualNetworkApplianceFactory().getNetworkDao();
        final Network network = networkDao.findById(_nicProfile.getNetworkId());
        return network;
    }

    protected boolean destroyPrivateGateway(final NetworkTopologyVisitor visitor) throws ConcurrentOperationException, ResourceUnavailableException {

        final NetworkModel networkModel = visitor.getVirtualNetworkApplianceFactory().getNetworkModel();
        if (!networkModel.isVmPartOfNetwork(_router.getId(), _privateGateway.getNetworkId())) {
            s_logger.debug("Router doesn't have nic for gateway " + _privateGateway + " so no need to removed it");
            return true;
        }

        final Network privateNetwork = networkModel.getNetwork(_privateGateway.getNetworkId());

        s_logger.debug("Releasing private ip for gateway " + _privateGateway + " from " + _router);

        _nicProfile = networkModel.getNicProfile(_router, privateNetwork.getId(), null);
        boolean result = visitor.visit(this);
        if (!result) {
            s_logger.warn("Failed to release private ip for gateway " + _privateGateway + " on router " + _router);
            return false;
        }

        // revoke network acl on the private gateway.
        final NetworkACLManager networkACLMgr = visitor.getVirtualNetworkApplianceFactory().getNetworkACLMgr();
        if (!networkACLMgr.revokeACLItemsForPrivateGw(_privateGateway)) {
            s_logger.debug("Failed to delete network acl items on " + _privateGateway + " from router " + _router);
            return false;
        }

        s_logger.debug("Removing router " + _router + " from private network " + privateNetwork + " as a part of delete private gateway");
        final VirtualMachineManager itMgr = visitor.getVirtualNetworkApplianceFactory().getItMgr();
        result = result && itMgr.removeVmFromNetwork(_router, privateNetwork, null);
        s_logger.debug("Private gateawy " + _privateGateway + " is removed from router " + _router);
        return result;
    }
}