package ioutils

import (
	"context"
	"sync"

	"github.com/royalcat/ctxio"
)

type ReaderReaderAtWrapper struct {
	mu     sync.Mutex
	rat    ctxio.ReaderAt
	offset int64
}

func NewReaderReaderAtWrapper(rat ctxio.ReaderAt) *ReaderReaderAtWrapper {
	return &ReaderReaderAtWrapper{
		rat: rat,
	}
}

var _ ctxio.Reader = (*ReaderReaderAtWrapper)(nil)
var _ ctxio.ReaderAt = (*ReaderReaderAtWrapper)(nil)
var _ ctxio.Closer = (*ReaderReaderAtWrapper)(nil)

// Read implements Reader.
func (r *ReaderReaderAtWrapper) Read(ctx context.Context, p []byte) (n int, err error) {
	r.mu.Lock()
	defer r.mu.Unlock()
	n, err = r.rat.ReadAt(ctx, p, r.offset)
	r.offset += int64(n)
	return n, err
}

// ReadAt implements ReaderAt.
func (r *ReaderReaderAtWrapper) ReadAt(ctx context.Context, p []byte, off int64) (n int, err error) {
	return r.rat.ReadAt(ctx, p, off)
}

// Close implements Closer.
func (r *ReaderReaderAtWrapper) Close(ctx context.Context) (err error) {
	if c, ok := r.rat.(ctxio.Closer); ok {
		err = c.Close(ctx)
		if err != nil {
			return err
		}
	}
	return nil
}