// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package directory

import (
	"fmt"
	"os"
	"path/filepath"
	"sort"

	"go.fuchsia.dev/fuchsia/tools/check-licenses/file"
	"go.fuchsia.dev/fuchsia/tools/check-licenses/project"
	"go.fuchsia.dev/fuchsia/tools/check-licenses/project/readme"
)

// Directory is an in memory representation of the state of the repository.
type Directory struct {
	Name     string           `json:"name,omitempty"`
	Path     string           `json:"path,omitempty"`
	Files    []*file.File     `json:"files,omitempty"`
	Children []*Directory     `json:"children,omitempty"`
	Parent   *Directory       `json:"-"`
	Project  *project.Project `json:"-"`
}

// Order implements sort.Interface for []*Directory based on the Path field.
type Order []*Directory

func (a Order) Len() int           { return len(a) }
func (a Order) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a Order) Less(i, j int) bool { return a[i].Path < a[j].Path }

// NewDirectory returns an instance of Directory.
func NewDirectory(root string, parent *Directory) (*Directory, error) {
	return newDirectoryWithConfig(root, parent, Config)
}

// Call NewDirectory with a passed-in config variable (instead of using
// the static Config variable). This allows for easier testing.
func newDirectoryWithConfig(root string, parent *Directory, config *DirectoryConfig) (*Directory, error) {
	d := Directory{}
	if RootDirectory == nil {
		RootDirectory = &d
	}

	d.Name = filepath.Base(root)
	d.Path = root
	d.Parent = parent
	d.Project = project.UnknownProject

	// If we are not at a "barrier" directory (e.g. prebuilt, third_party),
	// then the license info of the parent directory also applies to this directory.
	// Propagate that information down here.
	if !project.IsBarrier(root) && parent != nil {
		d.Project = parent.Project
	}

	if !project.IsBarrier(root) && parent != nil {
		// If we are not at a "barrier" directory (e.g. prebuilt, third_party),
		// then the license info of the parent directory also applies to this directory.
		// Propagate that information down here.
		d.Project = parent.Project
	}

	var r *readme.Readme
	var p *project.Project
	var err error

	// If a README.fuchsia file exists in the current directory, load it.
	if readmePath, exists := readmeFileExists(root); exists {
		if r, err = readme.NewReadmeFromFile(readmePath); err != nil {
			return nil, fmt.Errorf("error loading readme file [%s]: %w\n",
				readmePath, err)
		}
	} else if readmeFileWillNeverExist(root) {
		// Some 3P projects don't have (and never will have) a README.fuchsia file.
		// In those cases, generate an in-memory README file that describes
		// the project.
		if r, err = readme.NewReadmeCustom(root); err != nil {
			return nil, fmt.Errorf("error creating custom readme [%s]: %w\n",
				root, err)
		}
	}

	// If this project was already created during initialization, set it here.
	var ok bool
	if p, ok = project.AllProjects[root]; ok {
		d.Project = p
		r = d.Project.ReadmeFile
	} else if r != nil {
		// Create a new Project using the readme data.
		p, err = project.NewProject(r, root)
		if err != nil {
			return nil, err
		}
		d.Project = p
	}

	directoryContents, err := os.ReadDir(root)
	if err != nil {
		return nil, err
	}
	// Then traverse the rest of the contents of this directory.
	for _, item := range directoryContents {
		path := filepath.Join(root, item.Name())

		// Check the config file to see if we should skip this file / folder.
		if config.shouldSkip(path) {
			plusVal(Skipped, path)
			continue
		}

		// Directories
		if item.IsDir() {
			plus1(NumFolders)
			child, err := newDirectoryWithConfig(path, &d, config)
			if err != nil {
				return nil, err
			}
			d.Children = append(d.Children, child)
			continue
		}

		// Files
		fileType := file.RegularFile
		if file.IsPossibleLicenseFile(path) {
			fileType = file.SingleLicense
		}
		f, err := file.LoadFile(path, fileType, d.Project.Name)
		if err != nil {
			// Likely a symlink issue
			continue
		} else {
			plus1(NumFiles)
			d.Files = append(d.Files, f)
			d.Project.AddFile(f)
		}
	}

	sort.Sort(Order(d.Children))
	AllDirectories[d.Path] = &d
	return &d, nil
}
