package ui_test

import (
	. "github.com/cloudfoundry/bosh-cli/v7/ui"

	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"

	"github.com/cloudfoundry/bosh-cli/v7/ui/fakes"
)

type CallTracker struct {
	Seeks  []interface{}
	Closes int
}

type FakeSeekableReader struct {
	callTracker *CallTracker
}
type FakeReaderCloser struct{}

func (FakeSeekableReader) Read(_ []byte) (n int, err error) {
	panic("should not call")
}

func (FakeReaderCloser) Read(_ []byte) (n int, err error) {
	panic("should not call")
}

func (FakeReaderCloser) Close() error {
	panic("should not call")
}

func (r FakeSeekableReader) Seek(offset int64, whence int) (int64, error) {
	r.callTracker.Seeks = append(r.callTracker.Seeks, []interface{}{offset, whence})

	return 0, nil
}

func (r FakeSeekableReader) Close() error {
	r.callTracker.Closes++

	return nil
}

var _ = Describe("ReadCloserProxy", func() {
	Describe("Seek", func() {
		Context("when reader is seekable", func() {
			It("delegates to internal seeker", func() {
				seekerReader := FakeSeekableReader{
					callTracker: &CallTracker{},
				}
				fileReporter := NewFileReporter(&fakes.FakeUI{})
				readCloserProxy := fileReporter.TrackUpload(0, seekerReader)

				_, err := readCloserProxy.Seek(12, 42)
				Expect(err).ToNot(HaveOccurred())
				Expect(seekerReader.callTracker.Seeks).To(ContainElement([]interface{}{int64(12), 42}))
			})
		})

		Context("when reader is NOT seekable", func() {
			It("does not complain and returns 0, nil", func() {
				reader := FakeReaderCloser{}
				fileReporter := NewFileReporter(&fakes.FakeUI{})
				readCloserProxy := fileReporter.TrackUpload(0, reader)

				bytes, err := readCloserProxy.Seek(12, 42)
				Expect(err).ToNot(HaveOccurred())
				Expect(bytes).To(Equal(int64(0)))
			})
		})
	})

	Describe("Close", func() {
		It("closes the reader, uses the ui for bar output, and prints a newline", func() {
			fakeUI := &fakes.FakeUI{}
			seekerReader := FakeSeekableReader{
				callTracker: &CallTracker{},
			}
			fileReporter := NewFileReporter(fakeUI)
			readCloserProxy := fileReporter.TrackUpload(0, seekerReader)

			err := readCloserProxy.Close()
			Expect(err).ToNot(HaveOccurred())
			Expect(seekerReader.callTracker.Closes).To(Equal(1))
			uiSaid := fakeUI.Said
			Expect(len(uiSaid)).To(BeNumerically(">", 0))
			Expect(uiSaid[0]).To(ContainSubstring("[___"))
		})
	})
})
