package system

import (
	"io/fs"
	"os"
	"path/filepath"
)

type System struct{}

func (s *System) GetFileInfo(path string) (os.FileInfo, error) {
	f, err := os.OpenFile(path, os.O_RDONLY, 0644)
	defer func(f *os.File) {
		_ = f.Close()
	}(f)

	if err != nil {
		return nil, err
	}
	return f.Stat()
}

func (s *System) OpenFile(path string, flag int, perm fs.FileMode) (*os.File, error) {
	absPath, err := filepath.Abs(path)
	if err != nil {
		return nil, err
	}

	_, err = os.Stat(absPath)
	if err != nil {
		return nil, err
	}

	f, err := os.OpenFile(absPath, flag, perm)
	FileManager.Set(f, absPath, flag, perm)
	return f, err
}

func (s *System) ReadFile(path string, chunkId int64, chunkSize int64) ([]byte, error) {
	f := FileManager.Get(path, os.O_RDONLY, fs.FileMode(0644))
	if f == nil {
		return nil, os.ErrClosed
	}

	info, err := f.Stat()
	size := info.Size()

	if err != nil {
		return nil, err
	}

	offset := chunkId * chunkSize
	if offset+chunkSize > size {
		chunkSize = size - offset
	}

	data := make([]byte, chunkSize)
	_, err = f.ReadAt(data, offset)
	if err != nil {
		return nil, err
	}

	return data, nil
}

func (s *System) CloseFile(path string, flag int, perm fs.FileMode) {
	FileManager.Remove(path, flag, perm)
}
