package jobcontainers

import (
	"unicode/utf16"
	"unsafe"

	"github.com/pkg/errors"
	"golang.org/x/sys/windows"
)

// defaultEnvBlock will return a new environment block in the context of the user token
// `token`.
//
// This is almost a direct copy of the go stdlib implementation with some slight changes
// to force a valid token to be passed.
// https://github.com/golang/go/blob/f21be2fdc6f1becdbed1592ea0b245cdeedc5ac8/src/internal/syscall/execenv/execenv_windows.go#L24
func defaultEnvBlock(token windows.Token) (env []string, err error) {
	if token == 0 {
		return nil, errors.New("invalid token for creating environment block")
	}

	var block *uint16
	if err := windows.CreateEnvironmentBlock(&block, token, false); err != nil {
		return nil, err
	}
	defer func() {
		_ = windows.DestroyEnvironmentBlock(block)
	}()

	blockp := uintptr(unsafe.Pointer(block))
	for {
		// find NUL terminator
		end := unsafe.Pointer(blockp)
		for *(*uint16)(end) != 0 {
			end = unsafe.Pointer(uintptr(end) + 2)
		}

		n := (uintptr(end) - uintptr(unsafe.Pointer(blockp))) / 2
		if n == 0 {
			// environment block ends with empty string
			break
		}
		entry := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(blockp))[:n:n]
		env = append(env, string(utf16.Decode(entry)))
		blockp += 2 * (uintptr(len(entry)) + 1)
	}
	return
}
