package vfs

import (
	"context"
	"errors"
	"io/fs"
	"path"
	"time"

	"github.com/royalcat/ctxio"
	"go.opentelemetry.io/otel"
)

type File interface {
	IsDir() bool
	Size() int64

	fs.DirEntry

	ctxio.Reader
	ctxio.ReaderAt
	ctxio.Closer
}

var ErrNotImplemented = errors.New("not implemented")

var tracer = otel.Tracer("git.kmsign.ru/royalcat/tstor/src/vfs")

type Filesystem interface {
	// Open opens the named file for reading. If successful, methods on the
	// returned file can be used for reading; the associated file descriptor has
	// mode O_RDONLY.
	Open(ctx context.Context, filename string) (File, error)

	// ReadDir reads the directory named by dirname and returns a list of
	// directory entries.
	ReadDir(ctx context.Context, path string) ([]fs.DirEntry, error)

	Stat(ctx context.Context, filename string) (fs.FileInfo, error)
	Unlink(ctx context.Context, filename string) error

	// As filesystem mounted to some path, make sense to have the filesystem implement DirEntry
	fs.DirEntry
}

// readonly
const ROMode = fs.FileMode(0555)

type fileInfo struct {
	name  string
	size  int64
	isDir bool
}

var _ fs.FileInfo = &fileInfo{}
var _ fs.DirEntry = &fileInfo{}

func NewDirInfo(name string) *fileInfo {
	return &fileInfo{
		name:  path.Base(name),
		size:  0,
		isDir: true,
	}
}

func NewFileInfo(name string, size int64) *fileInfo {
	return &fileInfo{
		name:  path.Base(name),
		size:  size,
		isDir: false,
	}
}

func (fi *fileInfo) Info() (fs.FileInfo, error) {
	return fi, nil
}

func (fi *fileInfo) Type() fs.FileMode {
	if fi.isDir {
		return fs.ModeDir
	}

	return 0
}

func (fi *fileInfo) Name() string {
	return fi.name
}

func (fi *fileInfo) Size() int64 {
	return fi.size
}

func (fi *fileInfo) Mode() fs.FileMode {
	if fi.isDir {
		return ROMode | fs.ModeDir
	}

	return ROMode
}

func (fi *fileInfo) ModTime() time.Time {
	// TODO fix it
	return time.Time{}
}

func (fi *fileInfo) IsDir() bool {
	return fi.isDir
}

func (fi *fileInfo) Sys() interface{} {
	return nil
}