package vmomi

import (
	"context"

	"github.com/vmware/govmomi/object"
	"github.com/vmware/govmomi/property"
	"github.com/vmware/govmomi/vim25"
	"github.com/vmware/govmomi/vim25/mo"
)

type (
	MoVirtualMachine     mo.VirtualMachine
	ObjectVirtualMachine object.VirtualMachine

	VirtualMachine struct {
		c   *vim25.Client
		mvm *MoVirtualMachine
		ovm *ObjectVirtualMachine
	}
)

func makeVirtualMachine(c *vim25.Client, vm *MoVirtualMachine) *VirtualMachine {
	return &VirtualMachine{
		c:   c,
		mvm: vm,
		ovm: vm.GetOvm(c),
	}
}

func (v *VirtualMachine) Ovm() *ObjectVirtualMachine {
	return v.ovm
}

func (v *VirtualMachine) Mvm() *MoVirtualMachine {
	return v.mvm
}

func (v *VirtualMachine) Name() string {
	return v.mvm.Summary.Config.Name
}

func (v *VirtualMachine) Uuid() string {
	return v.mvm.Summary.Config.Uuid
}

func (v *VirtualMachine) PowerOn() (*object.Task, error) {
	return v.ovm.GetOvm().PowerOn(context.Background())
}

func (v *VirtualMachine) PowerOff() (*object.Task, error) {
	return v.ovm.GetOvm().PowerOff(context.Background())
}

func (v *VirtualMachine) Reset() (*object.Task, error) {
	return v.ovm.GetOvm().Reset(context.Background())
}

func (vm *MoVirtualMachine) GetMvm() *mo.VirtualMachine {
	return (*mo.VirtualMachine)(vm)
}

func (vm *MoVirtualMachine) GetOvm(c *vim25.Client) *ObjectVirtualMachine {
	return (*ObjectVirtualMachine)(object.NewVirtualMachine(c, vm.Reference()))
}

func (ovm *ObjectVirtualMachine) GetOvm() *object.VirtualMachine {
	return (*object.VirtualMachine)(ovm)
}

func (ovm *ObjectVirtualMachine) GetMvm(c *vim25.Client) (*MoVirtualMachine, error) {
	var mvm mo.VirtualMachine

	pc := property.DefaultCollector(c)
	return (*MoVirtualMachine)(&mvm), pc.RetrieveOne(context.Background(), ovm.Reference(), []string{}, &mvm)
}
