// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause

package dirfs

import (
	"context"
	"io/fs"
	"os"

	"github.com/tailscale/xnet/webdav"
	"tailscale.com/tailfs/tailfsimpl/shared"
)

// OpenFile implements interface webdav.Filesystem.
func (dfs *FS) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) {
	_, isStaticRoot := dfs.trimStaticRoot(name)
	if !isStaticRoot && !shared.IsRoot(name) {
		// Show a folder with no children to represent the requested child. In
		// practice, the children of this folder are never read, we just need
		// to give webdav a file here which it uses to call file.Stat(). So,
		// even though the Child may in fact have its own children, it doesn't
		// matter here.
		return &shared.DirFile{
			Info: shared.ReadOnlyDirInfo(name, dfs.now()),
			LoadChildren: func() ([]fs.FileInfo, error) {
				return nil, nil
			},
		}, nil
	}

	di, err := dfs.Stat(ctx, name)
	if err != nil {
		return nil, err
	}

	if dfs.StaticRoot != "" && !isStaticRoot {
		// Show a folder with a single subfolder that is the static root.
		return &shared.DirFile{
			Info: di,
			LoadChildren: func() ([]fs.FileInfo, error) {
				return []fs.FileInfo{
					shared.ReadOnlyDirInfo(dfs.StaticRoot, dfs.now()),
				}, nil
			},
		}, nil
	}

	// Show a folder with one subfolder for each Child of this FS.
	return &shared.DirFile{
		Info: di,
		LoadChildren: func() ([]fs.FileInfo, error) {
			childInfos := make([]fs.FileInfo, 0, len(dfs.Children))
			for _, c := range dfs.Children {
				if c.isAvailable() {
					childInfo := shared.ReadOnlyDirInfo(c.Name, dfs.now())
					childInfos = append(childInfos, childInfo)
				}
			}
			return childInfos, nil
		},
	}, nil
}