//go:build windows
// +build windows

package cfd

import (
	"github.com/go-ole/go-ole"
	"syscall"
	"unsafe"
)

var (
	procSHCreateItemFromParsingName = syscall.NewLazyDLL("Shell32.dll").NewProc("SHCreateItemFromParsingName")
	iidShellItem                    = ole.NewGUID("43826d1e-e718-42ee-bc55-a1e261c37bfe")
)

type iShellItem struct {
	vtbl *iShellItemVtbl
}

type iShellItemVtbl struct {
	iUnknownVtbl
	BindToHandler  uintptr
	GetParent      uintptr
	GetDisplayName uintptr // func (sigdnName SIGDN, ppszName *LPWSTR) HRESULT
	GetAttributes  uintptr
	Compare        uintptr
}

func newIShellItem(path string) (*iShellItem, error) {
	var shellItem *iShellItem
	pathPtr := ole.SysAllocString(path)
	defer func(v *int16) {
		_ = ole.SysFreeString(v)
	}(pathPtr)

	ret, _, _ := procSHCreateItemFromParsingName.Call(
		uintptr(unsafe.Pointer(pathPtr)),
		0,
		uintptr(unsafe.Pointer(iidShellItem)),
		uintptr(unsafe.Pointer(&shellItem)))
	return shellItem, hresultToError(ret)
}

func (vtbl *iShellItemVtbl) getDisplayName(objPtr unsafe.Pointer) (string, error) {
	var ptr *uint16
	ret, _, _ := syscall.SyscallN(vtbl.GetDisplayName,
		uintptr(objPtr),
		0x80058000, // SIGDN_FILESYSPATH,
		uintptr(unsafe.Pointer(&ptr)))
	if err := hresultToError(ret); err != nil {
		return "", err
	}
	defer ole.CoTaskMemFree(uintptr(unsafe.Pointer(ptr)))
	return ole.LpOleStrToString(ptr), nil
}
