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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.cloud.agent.api.to.DiskTO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.offering.ServiceOffering;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
import com.cloud.user.Account;
import com.cloud.utils.db.EntityManager;

/**
 * Implementation of VirtualMachineProfile.
 *
 */
public class VirtualMachineProfileImpl implements VirtualMachineProfile {

    VirtualMachine _vm;
    ServiceOffering _offering;
    VirtualMachineTemplate _template;
    UserVmDetailVO _userVmDetails;
    Map<Param, Object> _params;
    List<NicProfile> _nics = new ArrayList<NicProfile>();
    List<DiskTO> _disks = new ArrayList<DiskTO>();
    StringBuilder _bootArgs = new StringBuilder();
    Account _owner;
    BootloaderType _bootloader;
    Float cpuOvercommitRatio = 1.0f;
    Float memoryOvercommitRatio = 1.0f;

    VirtualMachine.Type _type;

    public VirtualMachineProfileImpl(VirtualMachine vm, VirtualMachineTemplate template, ServiceOffering offering, Account owner, Map<Param, Object> params) {
        _vm = vm;
        _template = template;
        _offering = offering;
        _params = params;
        _owner = owner;
        if (_params == null) {
            _params = new HashMap<Param, Object>();
        }
        if (vm != null)
        	_type = vm.getType();
    }

    public VirtualMachineProfileImpl(VirtualMachine vm) {
        this(vm, null, null, null, null);
    }

    public VirtualMachineProfileImpl(VirtualMachine.Type type) {
        _type = type;
    }

    @Override
    public String toString() {
        return _vm.toString();
    }

    @Override
    public VirtualMachine getVirtualMachine() {
        return _vm;
    }

    @Override
    public ServiceOffering getServiceOffering() {
        if (_offering == null) {
            _offering = s_entityMgr.findById(ServiceOffering.class, _vm.getServiceOfferingId());
        }
        return _offering;
    }

    @Override
    public void setParameter(Param name, Object value) {
        _params.put(name, value);
    }

    @Override
    public void setBootLoaderType(BootloaderType bootLoader) {
    	_bootloader = bootLoader;
    }

    @Override
    public VirtualMachineTemplate getTemplate() {
        if (_template == null && _vm != null) {
            _template = s_entityMgr.findById(VirtualMachineTemplate.class, _vm.getTemplateId());
        }
        return _template;
    }

    @Override
    public HypervisorType getHypervisorType() {
        return _vm.getHypervisorType();
    }

    @Override
    public long getTemplateId() {
        return _vm.getTemplateId();
    }

    @Override
    public long getServiceOfferingId() {
        return _vm.getServiceOfferingId();
    }

    @Override
    public long getId() {
        return _vm.getId();
    }

    @Override
    public String getUuid() {
	return _vm.getUuid();
    }

    public void setNics(List<NicProfile> nics) {
        _nics = nics;
    }

    public void setDisks(List<DiskTO> disks) {
        _disks = disks;
    }

    @Override
    public List<NicProfile> getNics() {
        return _nics;
    }

    @Override
    public List<DiskTO> getDisks() {
        return _disks;
    }

    @Override
    public void addNic(int index, NicProfile nic) {
        _nics.add(index, nic);
    }

    @Override
    public void addDisk(int index, DiskTO disk) {
        _disks.add(index, disk);
    }

    @Override
    public StringBuilder getBootArgsBuilder() {
        return _bootArgs;
    }

    @Override
    public void addBootArgs(String... args) {
        for (String arg : args) {
            _bootArgs.append(arg).append(" ");
        }
    }

    @Override
    public VirtualMachine.Type getType() {
        return _type;
    }

    @Override
    public Account getOwner() {
        if (_owner == null) {
            _owner = s_entityMgr.findById(Account.class, _vm.getAccountId());
        }
        return _owner;
    }

    @Override
    public String getBootArgs() {
        return _bootArgs.toString();
    }

    static EntityManager s_entityMgr;

    static void init(EntityManager entityMgr) {
        s_entityMgr = entityMgr;
    }

    @Override
    public void addNic(NicProfile nic) {
        _nics.add(nic);
    }

    @Override
    public void addDisk(DiskTO disk) {
        _disks.add(disk);
    }

    @Override
    public Object getParameter(Param name) {
        return _params.get(name);
    }

    @Override
    public String getHostName() {
        return _vm.getHostName();
    }

    @Override
    public String getInstanceName() {
        return _vm.getInstanceName();
    }

	@Override
	public BootloaderType getBootLoaderType() {
		return _bootloader;
	}

	@Override
	public Map<Param, Object> getParameters() {
	    return _params;
	}

	public void setServiceOffering(ServiceOfferingVO offering) {
		_offering = offering;
	}

    public void setCpuOvercommitRatio(Float cpuOvercommitRatio) {
        this.cpuOvercommitRatio = cpuOvercommitRatio;

    }

    public void setMemoryOvercommitRatio(Float memoryOvercommitRatio) {
        this.memoryOvercommitRatio = memoryOvercommitRatio;

    }

    @Override
    public Float getCpuOvercommitRatio() {
        return  cpuOvercommitRatio;
    }

    @Override
    public Float getMemoryOvercommitRatio() {
        return memoryOvercommitRatio;
    }
}
