package archive

import (
	"context"
	"fmt"
	"io"

	"git.kmsign.ru/royalcat/tstor/server/pkg/ioutils"
	"git.kmsign.ru/royalcat/tstor/server/src/vfs"
	"github.com/nwaples/rardecode/v2"
	"github.com/royalcat/ctxio"
)

func (d *Daemon) RarLoader(ctx context.Context, archivePath string, f vfs.File, size int64) (map[string]fileEntry, error) {
	hash, err := vfs.FileHash(ctx, f)
	if err != nil {
		return nil, err
	}

	reader := ioutils.WrapIoReadSeeker(ctx, f, size)

	r, err := rardecode.NewReader(reader)
	if err != nil {
		return nil, err
	}

	out := make(map[string]fileEntry)
	for {
		header, err := r.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return nil, err
		}

		name := header.Name
		af := func(ctx context.Context) (ctxio.ReadCloser, error) {
			reader := ioutils.WrapIoReadSeeker(ctx, f, size)
			r, err := rardecode.NewReader(reader)
			if err != nil {
				return nil, err
			}

			for header, err := r.Next(); err != io.EOF; header, err = r.Next() {
				if err != nil {
					return nil, err
				}
				if header.Name == name {
					return ctxio.NopCloser(ctxio.WrapIoReader(r)), nil
				}
			}
			return nil, fmt.Errorf("file with name '%s' not found", name)
		}

		rr := newRandomReaderFromLinear(d.blockcache, archiveFileIndex{archiveHash: hash, filename: header.Name}, header.UnPackedSize, af)

		out[vfs.AbsPath(header.Name)] = fileEntry{
			FileInfo: vfs.NewFileInfo(header.Name, header.UnPackedSize, header.ModificationTime),
			open: func(ctx context.Context) (vfs.File, error) {
				return newArchiveFile(header.Name, header.UnPackedSize, rr), nil
			},
		}
	}

	return out, nil
}