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

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

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

import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import com.cloud.agent.AgentManager;
import com.cloud.agent.api.StartupBrocadeVcsCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.commands.AddBrocadeVcsDeviceCmd;
import com.cloud.api.commands.DeleteBrocadeVcsDeviceCmd;
import com.cloud.api.commands.ListBrocadeVcsDeviceNetworksCmd;
import com.cloud.api.commands.ListBrocadeVcsDevicesCmd;
import com.cloud.api.response.BrocadeVcsDeviceResponse;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.dc.dao.VlanDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.DetailVO;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.network.BrocadeVcsDeviceVO;
import com.cloud.network.IpAddressManager;
import com.cloud.network.Network;
import com.cloud.network.Networks;
import com.cloud.network.PhysicalNetwork;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkModel;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.dao.BrocadeVcsDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkServiceMapDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.resource.BrocadeVcsResource;
import com.cloud.offering.NetworkOffering;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceState;
import com.cloud.resource.ResourceStateAdapter;
import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallback;
import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.NicDao;

@Component
public class BrocadeVcsElement extends AdapterBase implements NetworkElement, ResourceStateAdapter, BrocadeVcsElementService {
    private static final Logger s_logger = Logger.getLogger(BrocadeVcsElement.class);

    private static final Map<Service, Map<Capability, String>> capabilities = setCapabilities();

    @Inject
    NicDao _nicDao;
    @Inject
    ResourceManager _resourceMgr;
    @Inject
    PhysicalNetworkDao _physicalNetworkDao;
    @Inject
    PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
    @Inject
    protected BrocadeVcsDao _brocadeVcsDao;
    @Inject
    HostDetailsDao _hostDetailsDao;
    @Inject
    HostDao _hostDao;
    @Inject
    AgentManager _agentMgr;
    @Inject
    NetworkDao _networkDao;
    @Inject
    NetworkOrchestrationService _networkManager;
    @Inject
    NetworkModel _networkModel;
    @Inject
    ConfigurationManager _configMgr;
    @Inject
    NetworkServiceMapDao _ntwkSrvcDao;
    @Inject
    VlanDao _vlanDao;
    @Inject
    IpAddressManager _ipAddrMgr;

    @Override
    public Map<Service, Map<Capability, String>> getCapabilities() {
        return capabilities;
    }

    @Override
    public Provider getProvider() {
        return Network.Provider.BrocadeVcs;
    }

    protected boolean canHandle(Network network, Service service) {
        s_logger.debug("Checking if BrocadeVcsElement can handle service " + service.getName() + " on network " + network.getDisplayText());
        if (network.getBroadcastDomainType() != BroadcastDomainType.Vcs) {
            return false;
        }

        if (!_networkModel.isProviderForNetwork(getProvider(), network.getId())) {
            s_logger.debug("BrocadeVcsElement is not a provider for network " + network.getDisplayText());
            return false;
        }

        if (!_ntwkSrvcDao.canProviderSupportServiceInNetwork(network.getId(), service, Network.Provider.BrocadeVcs)) {
            s_logger.debug("BrocadeVcsElement can't provide the " + service.getName() + " service on network " + network.getDisplayText());
            return false;
        }

        return true;
    }

    @Override
    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
        super.configure(name, params);
        _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
        return true;
    }

    @Override
    public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException,
            ResourceUnavailableException, InsufficientCapacityException {
        s_logger.debug("entering BrocadeVcsElement implement function for network " + network.getDisplayText() + " (state " + network.getState() + ")");

        if (!canHandle(network, Service.Connectivity)) {
            return false;
        }

        return true;
    }

    @Override
    public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException,
            ResourceUnavailableException, InsufficientCapacityException {

        if (!canHandle(network, Service.Connectivity)) {
            return false;
        }

        return true;
    }

    @Override
    public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {

        if (!canHandle(network, Service.Connectivity)) {
            return false;
        }

        return true;
    }

    @Override
    public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
        if (!canHandle(network, Service.Connectivity)) {
            return false;
        }

        return true;
    }

    @Override
    public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
        if (!canHandle(network, Service.Connectivity)) {
            return false;
        }

        return true;
    }

    @Override
    public boolean isReady(PhysicalNetworkServiceProvider provider) {
        return true;
    }

    @Override
    public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
        // Nothing to do here.
        return true;
    }

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

    @Override
    public boolean verifyServicesCombination(Set<Service> services) {

        if (!services.contains(Service.Connectivity)) {
            s_logger.warn("Unable to provide services without Connectivity service enabled for this element");
            return false;
        }
        return true;
    }

    private static Map<Service, Map<Capability, String>> setCapabilities() {
        Map<Service, Map<Capability, String>> capabilities = new HashMap<Service, Map<Capability, String>>();

        // L2 Support
        capabilities.put(Service.Connectivity, null);

        return capabilities;
    }

    @Override
    public List<Class<?>> getCommands() {
        List<Class<?>> cmdList = new ArrayList<Class<?>>();
        cmdList.add(AddBrocadeVcsDeviceCmd.class);
        cmdList.add(DeleteBrocadeVcsDeviceCmd.class);
        cmdList.add(ListBrocadeVcsDeviceNetworksCmd.class);
        cmdList.add(ListBrocadeVcsDevicesCmd.class);
        return cmdList;
    }

    @Override
    @DB
    public BrocadeVcsDeviceVO addBrocadeVcsDevice(AddBrocadeVcsDeviceCmd cmd) {
        ServerResource resource = new BrocadeVcsResource();
        final String deviceName = Network.Provider.BrocadeVcs.getName();
        NetworkDevice networkDevice = NetworkDevice.getNetworkDevice(deviceName);
        if (networkDevice == null) {
            throw new CloudRuntimeException("No network device found for " + deviceName);
        }
        final Long physicalNetworkId = cmd.getPhysicalNetworkId();
        PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
        if (physicalNetwork == null) {
            throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId);
        }
        long zoneId = physicalNetwork.getDataCenterId();

        final PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(physicalNetwork.getId(),
                networkDevice.getNetworkServiceProvder());
        if (ntwkSvcProvider == null) {
            throw new CloudRuntimeException("Network Service Provider: " + networkDevice.getNetworkServiceProvder() + " is not enabled in the physical network: "
                    + physicalNetworkId + "to add this device");
        } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
            throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() + " is in shutdown state in the physical network: "
                    + physicalNetworkId + "to add this device");
        }

        Map<String, String> params = new HashMap<String, String>();
        params.put("guid", UUID.randomUUID().toString());
        params.put("zoneId", String.valueOf(physicalNetwork.getDataCenterId()));
        params.put("physicalNetworkId", String.valueOf(physicalNetwork.getId()));
        params.put("name", "Brocade VCS - " + cmd.getHost());
        params.put("ip", cmd.getHost());
        params.put("adminuser", cmd.getUsername());
        params.put("adminpass", cmd.getPassword());

        Map<String, Object> hostdetails = new HashMap<String, Object>();
        hostdetails.putAll(params);

        try {
            resource.configure(cmd.getHost(), hostdetails);

            final Host host = _resourceMgr.addHost(zoneId, resource, Host.Type.L2Networking, params);
            if (host != null) {
                return Transaction.execute(new TransactionCallback<BrocadeVcsDeviceVO>() {
                    @Override
                    public BrocadeVcsDeviceVO doInTransaction(TransactionStatus status) {
                        BrocadeVcsDeviceVO brocadeVcsDevice = new BrocadeVcsDeviceVO(host.getId(), physicalNetworkId, ntwkSvcProvider.getProviderName(), deviceName);
                        _brocadeVcsDao.persist(brocadeVcsDevice);

                        DetailVO detail = new DetailVO(host.getId(), "brocadevcsdeviceid", String.valueOf(brocadeVcsDevice.getId()));
                        _hostDetailsDao.persist(detail);

                        return brocadeVcsDevice;
                    }
                });
            } else {
                throw new CloudRuntimeException("Failed to add Brocade VCS Switch due to internal error.");
            }
        } catch (ConfigurationException e) {
            throw new CloudRuntimeException(e.getMessage());
        }

    }

    @Override
    public BrocadeVcsDeviceResponse createBrocadeVcsDeviceResponse(BrocadeVcsDeviceVO brocadeVcsDeviceVO) {
        HostVO brocadeVcsHost = _hostDao.findById(brocadeVcsDeviceVO.getHostId());
        _hostDao.loadDetails(brocadeVcsHost);

        BrocadeVcsDeviceResponse response = new BrocadeVcsDeviceResponse();
        response.setDeviceName(brocadeVcsDeviceVO.getDeviceName());
        PhysicalNetwork pnw = ApiDBUtils.findPhysicalNetworkById(brocadeVcsDeviceVO.getPhysicalNetworkId());
        if (pnw != null) {
            response.setPhysicalNetworkId(pnw.getUuid());
        }
        response.setId(brocadeVcsDeviceVO.getUuid());
        response.setProviderName(brocadeVcsDeviceVO.getProviderName());
        response.setHostName(brocadeVcsHost.getDetail("ip"));
        response.setObjectName("brocadevcsdevice");
        return response;
    }

    @Override
    public boolean deleteBrocadeVcsDevice(DeleteBrocadeVcsDeviceCmd cmd) {
        Long brocadeDeviceId = cmd.getBrocadeVcsDeviceId();
        BrocadeVcsDeviceVO brocadeVcsDevice = _brocadeVcsDao.findById(brocadeDeviceId);
        if (brocadeVcsDevice == null) {
            throw new InvalidParameterValueException("Could not find a brocade vcs switch with id " + brocadeVcsDevice);
        }

        // Find the physical network we work for
        Long physicalNetworkId = brocadeVcsDevice.getPhysicalNetworkId();
        PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
        if (physicalNetwork != null) {
            // Lets see if there are networks that use us
            // Find the brocade networks on this physical network
            List<NetworkVO> networkList = _networkDao.listByPhysicalNetwork(physicalNetworkId);
            if (networkList != null) {
                // Networks with broadcast type vcs are ours
                for (NetworkVO network : networkList) {
                    if (network.getBroadcastDomainType() == Networks.BroadcastDomainType.Vcs) {
                        if ((network.getState() != Network.State.Shutdown) && (network.getState() != Network.State.Destroy)) {
                            throw new CloudRuntimeException("This Brocade VCS Switch can not be deleted as there are one or more logical networks provisioned by cloudstack.");
                        }
                    }
                }
            }
        }

        HostVO brocadeHost = _hostDao.findById(brocadeVcsDevice.getHostId());
        Long hostId = brocadeHost.getId();

        brocadeHost.setResourceState(ResourceState.Maintenance);
        _hostDao.update(hostId, brocadeHost);
        _resourceMgr.deleteHost(hostId, false, false);

        _brocadeVcsDao.remove(brocadeDeviceId);
        return true;
    }

    @Override
    public List<BrocadeVcsDeviceVO> listBrocadeVcsDevices(ListBrocadeVcsDevicesCmd cmd) {
        Long physicalNetworkId = cmd.getPhysicalNetworkId();
        Long brocadeVcsDeviceId = cmd.getBrocadeVcsDeviceId();
        List<BrocadeVcsDeviceVO> responseList = new ArrayList<BrocadeVcsDeviceVO>();

        if (physicalNetworkId == null && brocadeVcsDeviceId == null) {
            throw new InvalidParameterValueException("Either physical network Id or brocade vcs switch Id must be specified");
        }

        if (brocadeVcsDeviceId != null) {
            BrocadeVcsDeviceVO brocadeVcsDevice = _brocadeVcsDao.findById(brocadeVcsDeviceId);
            if (brocadeVcsDevice == null) {
                throw new InvalidParameterValueException("Could not find Brocade VCS Switch with id: " + brocadeVcsDeviceId);
            }
            responseList.add(brocadeVcsDevice);
        } else {
            PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
            if (physicalNetwork == null) {
                throw new InvalidParameterValueException("Could not find a physical network with id: " + physicalNetworkId);
            }
            responseList = _brocadeVcsDao.listByPhysicalNetwork(physicalNetworkId);
        }

        return responseList;
    }

    @Override
    public List<? extends Network> listBrocadeVcsDeviceNetworks(ListBrocadeVcsDeviceNetworksCmd cmd) {
        Long brocadeDeviceId = cmd.getBrocadeVcsDeviceId();
        BrocadeVcsDeviceVO brocadeVcsDevice = _brocadeVcsDao.findById(brocadeDeviceId);
        if (brocadeVcsDevice == null) {
            throw new InvalidParameterValueException("Could not find a Brocade VCS Switch with id " + brocadeDeviceId);
        }

        // Find the physical network we work for
        Long physicalNetworkId = brocadeVcsDevice.getPhysicalNetworkId();
        PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
        if (physicalNetwork == null) {
            // No such physical network, so no provisioned networks
            return Collections.emptyList();
        }

        // Find the brocade networks on this physical network
        List<NetworkVO> networkList = _networkDao.listByPhysicalNetwork(physicalNetworkId);
        if (networkList == null) {
            return Collections.emptyList();
        }

        // Networks with broadcast type vcs are ours
        List<NetworkVO> responseList = new ArrayList<NetworkVO>();
        for (NetworkVO network : networkList) {
            if (network.getBroadcastDomainType() == Networks.BroadcastDomainType.Vcs) {
                responseList.add(network);
            }
        }

        return responseList;
    }

    @Override
    public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details, List<String> hostTags) {
        if (!(startup[0] instanceof StartupBrocadeVcsCommand)) {
            return null;
        }
        host.setType(Host.Type.L2Networking);
        return host;
    }

    @Override
    public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
        if (!(host.getType() == Host.Type.L2Networking)) {
            return null;
        }
        return new DeleteHostAnswer(true);
    }

}
