package scanner

import (
	"context"
	"os"
	"path/filepath"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gstruct"
)

var _ = Describe("walk_dir_tree", func() {
	baseDir := filepath.Join("tests", "fixtures")

	Describe("walkDirTree", func() {
		It("reads all info correctly", func() {
			var collected = dirMap{}
			results := make(walkResults, 5000)
			var err error
			go func() {
				err = walkDirTree(context.TODO(), baseDir, results)
			}()

			for {
				stats, more := <-results
				if !more {
					break
				}
				collected[stats.Path] = stats
			}

			Expect(err).To(BeNil())
			Expect(collected[baseDir]).To(MatchFields(IgnoreExtras, Fields{
				"HasImages":       BeTrue(),
				"HasPlaylist":     BeFalse(),
				"AudioFilesCount": BeNumerically("==", 4),
			}))
			Expect(collected[filepath.Join(baseDir, "playlists")].HasPlaylist).To(BeTrue())
			Expect(collected).To(HaveKey(filepath.Join(baseDir, "symlink2dir")))
			Expect(collected).To(HaveKey(filepath.Join(baseDir, "empty_folder")))
		})
	})

	Describe("isDirOrSymlinkToDir", func() {
		It("returns true for normal dirs", func() {
			dirEntry, _ := getDirEntry("tests", "fixtures")
			Expect(isDirOrSymlinkToDir(baseDir, dirEntry)).To(BeTrue())
		})
		It("returns true for symlinks to dirs", func() {
			dirEntry, _ := getDirEntry(baseDir, "symlink2dir")
			Expect(isDirOrSymlinkToDir(baseDir, dirEntry)).To(BeTrue())
		})
		It("returns false for files", func() {
			dirEntry, _ := getDirEntry(baseDir, "test.mp3")
			Expect(isDirOrSymlinkToDir(baseDir, dirEntry)).To(BeFalse())
		})
		It("returns false for symlinks to files", func() {
			dirEntry, _ := getDirEntry(baseDir, "symlink")
			Expect(isDirOrSymlinkToDir(baseDir, dirEntry)).To(BeFalse())
		})
	})
	Describe("isDirIgnored", func() {
		It("returns false for normal dirs", func() {
			dirEntry, _ := getDirEntry(baseDir, "empty_folder")
			Expect(isDirIgnored(baseDir, dirEntry)).To(BeFalse())
		})
		It("returns true when folder contains .ndignore file", func() {
			dirEntry, _ := getDirEntry(baseDir, "ignored_folder")
			Expect(isDirIgnored(baseDir, dirEntry)).To(BeTrue())
		})
		It("returns true when folder name starts with a `.`", func() {
			dirEntry, _ := getDirEntry(baseDir, ".hidden_folder")
			Expect(isDirIgnored(baseDir, dirEntry)).To(BeTrue())
		})
		It("returns false when folder name starts with ellipses", func() {
			dirEntry, _ := getDirEntry(baseDir, "...unhidden_folder")
			Expect(isDirIgnored(baseDir, dirEntry)).To(BeFalse())
		})
	})
})

func getDirEntry(baseDir, name string) (os.DirEntry, error) {
	dirEntries, _ := os.ReadDir(baseDir)
	for _, entry := range dirEntries {
		if entry.Name() == name {
			return entry, nil
		}
	}
	return nil, os.ErrNotExist
}
