package rclone

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

	"git.kmsign.ru/royalcat/tstor/server/src/vfs"
	rclonefs "github.com/rclone/rclone/fs"
)

type fsWrapper struct {
	vfs.DefaultFS
	fs rclonefs.Fs
}

// Open implements vfs.Filesystem.
func (w *fsWrapper) Open(ctx context.Context, filename string) (vfs.File, error) {
	obj, err := w.fs.NewObject(ctx, filename)
	if err != nil {
		return nil, err
	}

	return &fileWrapper{name: filename, obj: obj}, nil
}

// ReadDir implements vfs.Filesystem.
func (w *fsWrapper) ReadDir(ctx context.Context, path string) ([]fs.DirEntry, error) {
	panic("unimplemented")

	// path = vfs.RemoveTrailingSlash(path)

	// entries, err := w.fs.List(ctx, path)
	// if err != nil {
	// 	return nil, err
	// }

	// out := make([]fs.DirEntry, 0, len(entries))
	// for _, e := range entries {

	// }

}

// Rename implements vfs.Filesystem.
func (f *fsWrapper) Rename(ctx context.Context, oldpath string, newpath string) error {
	panic("unimplemented")
}

// Stat implements vfs.Filesystem.
func (f *fsWrapper) Stat(ctx context.Context, filename string) (fs.FileInfo, error) {
	panic("unimplemented")
}

// Type implements vfs.Filesystem.
// Subtle: this method shadows the method (DefaultFS).Type of fsWrapper.DefaultFS.
func (f *fsWrapper) Type() fs.FileMode {
	panic("unimplemented")
}

// Unlink implements vfs.Filesystem.
func (f *fsWrapper) Unlink(ctx context.Context, filename string) error {
	panic("unimplemented")
}

var _ vfs.Filesystem = (*fsWrapper)(nil)

type fileWrapper struct {
	name string
	obj  rclonefs.Object
}

var _ vfs.File = (*fileWrapper)(nil)

// Close implements vfs.File.
func (f *fileWrapper) Close(ctx context.Context) error {
	return f.Close(ctx)
}

// Info implements vfs.File.
func (f *fileWrapper) Info() (fs.FileInfo, error) {
	return vfs.NewFileInfo(f.name, f.Size(), time.Time{}), nil
}

// IsDir implements vfs.File.
func (f *fileWrapper) IsDir() bool {
	return false
}

// Name implements vfs.File.
func (f *fileWrapper) Name() string {
	return f.name
}

// Read implements vfs.File.
func (f *fileWrapper) Read(ctx context.Context, p []byte) (n int, err error) {
	panic("unimplemented")
}

// Seek implements vfs.File.
func (f *fileWrapper) Seek(offset int64, whence int) (int64, error) {
	panic("unimplemented")
}

// ReadAt implements vfs.File.
func (f *fileWrapper) ReadAt(ctx context.Context, p []byte, off int64) (n int, err error) {
	rc, err := f.obj.Open(ctx, &rclonefs.RangeOption{Start: off, End: off + int64(len(p))})
	if err != nil {
		return 0, err
	}
	defer rc.Close()

	return rc.Read(p)
}

// Size implements vfs.File.
func (f *fileWrapper) Size() int64 {
	return f.Size()
}

// Type implements vfs.File.
func (f *fileWrapper) Type() fs.FileMode {
	return vfs.ModeFileRO
}