// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package os

import (
	"internal/syscall/windows"
	"io"
	"runtime"
	"sync"
	"syscall"
	"unicode/utf16"
	"unsafe"
)

// Auxiliary information if the File describes a directory
type dirInfo struct {
	// buf is a slice pointer so the slice header
	// does not escape to the heap when returning
	// buf to dirBufPool.
	buf  *[]byte // buffer for directory I/O
	bufp int     // location of next record in buf
	vol  uint32
}

const (
	// dirBufSize is the size of the dirInfo buffer.
	// The buffer must be big enough to hold at least a single entry.
	// The filename alone can be 512 bytes (MAX_PATH*2), and the fixed part of
	// the FILE_ID_BOTH_DIR_INFO structure is 105 bytes, so dirBufSize
	// should not be set below 1024 bytes (512+105+safety buffer).
	// Windows 8.1 and earlier only works with buffer sizes up to 64 kB.
	dirBufSize = 64 * 1024 // 64kB
)

var dirBufPool = sync.Pool{
	New: func() any {
		// The buffer must be at least a block long.
		buf := make([]byte, dirBufSize)
		return &buf
	},
}

func (d *dirInfo) close() {
	if d.buf != nil {
		dirBufPool.Put(d.buf)
		d.buf = nil
	}
}

func (file *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) {
	// If this file has no dirinfo, create one.
	var infoClass uint32 = windows.FileIdBothDirectoryInfo
	if file.dirinfo == nil {
		// vol is used by os.SameFile.
		// It is safe to query it once and reuse the value.
		// Hard links are not allowed to reference files in other volumes.
		// Junctions and symbolic links can reference files and directories in other volumes,
		// but the reparse point should still live in the parent volume.
		var vol uint32
		err = windows.GetVolumeInformationByHandle(file.pfd.Sysfd, nil, 0, &vol, nil, nil, nil, 0)
		runtime.KeepAlive(file)
		if err != nil {
			err = &PathError{Op: "readdir", Path: file.name, Err: err}
			return
		}
		infoClass = windows.FileIdBothDirectoryRestartInfo
		file.dirinfo = new(dirInfo)
		file.dirinfo.buf = dirBufPool.Get().(*[]byte)
		file.dirinfo.vol = vol
	}
	d := file.dirinfo
	wantAll := n <= 0
	if wantAll {
		n = -1
	}
	for n != 0 {
		// Refill the buffer if necessary
		if d.bufp == 0 {
			err = windows.GetFileInformationByHandleEx(file.pfd.Sysfd, infoClass, (*byte)(unsafe.Pointer(&(*d.buf)[0])), uint32(len(*d.buf)))
			runtime.KeepAlive(file)
			if err != nil {
				if err == syscall.ERROR_NO_MORE_FILES {
					break
				}
				if s, _ := file.Stat(); s != nil && !s.IsDir() {
					err = &PathError{Op: "readdir", Path: file.name, Err: syscall.ENOTDIR}
				} else {
					err = &PathError{Op: "GetFileInformationByHandleEx", Path: file.name, Err: err}
				}
				return
			}
			infoClass = windows.FileIdBothDirectoryInfo
		}
		// Drain the buffer
		var islast bool
		for n != 0 && !islast {
			info := (*windows.FILE_ID_BOTH_DIR_INFO)(unsafe.Pointer(&(*d.buf)[d.bufp]))
			d.bufp += int(info.NextEntryOffset)
			islast = info.NextEntryOffset == 0
			if islast {
				d.bufp = 0
			}
			nameslice := unsafe.Slice(&info.FileName[0], info.FileNameLength/2)
			name := string(utf16.Decode(nameslice))
			if name == "." || name == ".." { // Useless names
				continue
			}
			if mode == readdirName {
				names = append(names, name)
			} else {
				f := newFileStatFromFileIDBothDirInfo(info)
				f.name = name
				f.vol = d.vol
				// f.path is used by os.SameFile to decide if it needs
				// to fetch vol, idxhi and idxlo. But these are already set,
				// so set f.path to "" to prevent os.SameFile doing it again.
				f.path = ""
				if mode == readdirDirEntry {
					dirents = append(dirents, dirEntry{f})
				} else {
					infos = append(infos, f)
				}
			}
			n--
		}
	}
	if !wantAll && len(names)+len(dirents)+len(infos) == 0 {
		return nil, nil, nil, io.EOF
	}
	return names, dirents, infos, nil
}

type dirEntry struct {
	fs *fileStat
}

func (de dirEntry) Name() string            { return de.fs.Name() }
func (de dirEntry) IsDir() bool             { return de.fs.IsDir() }
func (de dirEntry) Type() FileMode          { return de.fs.Mode().Type() }
func (de dirEntry) Info() (FileInfo, error) { return de.fs, nil }
