// 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 world

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"

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

func (w *World) FilterProjects() error {
	projects := make([]*project.Project, 0)
	projectsMap := make(map[*project.Project]bool, 0)

	filepaths := make([]string, 0)
	var err error

	if isDir(Config.Target) {
		w.Status.WriteString(fmt.Sprintf("Filtering projects using a folder prefix check: `%s`\n", Config.Target))
		filepaths = w.FilterProjectsUsingDirectoryPrefix(filepaths)
	}

	filepaths, err = w.FilterExtraProjects(filepaths)
	if err != nil {
		return err
	}

	fileMap, err := w.getFileMap()
	if err != nil {
		return err
	}

	// Loop through the content, cleaning up the path strings
	// so we can map them to entries in our project map.
	for _, fp := range filepaths {
		if p, ok := fileMap[fp]; ok {
			projectsMap[p] = true
		}
	}

	for p := range projectsMap {
		projects = append(projects, p)
	}
	sort.Sort(project.Order(projects))

	w.FilteredProjects = projects

	filteredCount := len(w.FilteredProjects)
	totalCount := len(w.Projects)
	filteredOutCount := totalCount - filteredCount
	w.Status.WriteString(fmt.Sprintf("%v projects remain (filtered out %v from the full list of %v projects).\n", filteredCount, filteredOutCount, totalCount))
	return nil
}

func (w *World) FilterProjectsUsingDirectoryPrefix(filepaths []string) []string {
	for _, p := range w.Projects {
		for _, f := range p.Files {
			if strings.HasPrefix(f.Path, Config.Target) {
				filepaths = append(filepaths, f.Path)
			}
		}
	}
	return filepaths
}

func (w *World) FilterExtraProjects(filepaths []string) ([]string, error) {
	for _, projectFile := range Config.Filters {
		w.Status.WriteString(fmt.Sprintf("Adding additional projects from json file: `%s`\n", projectFile))

		f, err := os.Open(projectFile)
		if err != nil {
			return filepaths, err
		}
		defer f.Close()

		content, err := ioutil.ReadAll(f)
		if err != nil {
			return filepaths, err
		}

		projects := make([]string, 0)
		if err = json.Unmarshal(content, &projects); err != nil {
			return filepaths, fmt.Errorf("Failed to unmarshal project json file [%v]: %v\n", projectFile, err)
		}
		for _, p := range projects {
			filepaths = append(filepaths, p)
		}
	}

	return filepaths, nil
}

func (w *World) getFileMap() (map[string]*project.Project, error) {
	// Create a mapping that goes from file path to project,
	// so we can retrieve the projects that match dependencies in the
	// gn gen file.
	fileMap := make(map[string]*project.Project, 0)
	for _, p := range project.AllProjects {
		allFiles := make([]*file.File, 0)
		allFiles = append(allFiles, p.Files...)
		allFiles = append(allFiles, p.LicenseFile...)
		for _, f := range allFiles {
			path := f.Path
			if strings.Contains(f.Path, Config.FuchsiaDir) {
				var err error
				path, err = filepath.Rel(Config.FuchsiaDir, f.Path)
				if err != nil {
					return nil, err
				}
			}
			filePath := "//" + path
			folderPath := "//" + filepath.Dir(path)

			// "gn gen" may reveal that the current workspace has a a dependency on a LICENSE file.
			// That LICENSE file may be used in two or more different projects across fuchsia.git.
			// There's no way for us to tell which project actually contributes to the build.
			//
			// We want to deterministically generate the final NOTICE file, so in this situation
			// we simply choose the project that comes first alphabetically.
			//
			// In practice this simple strategy should be OK. "gn desc" / "gn gen" will undoubtedly
			// also have dependencies on other files in the project, which will ensure that the correct
			// project is included (even if we also occasionally include an unrelated one).
			if otherP, ok := fileMap[filePath]; ok {
				if p.Root < otherP.Root {
					fileMap[filePath] = p
					fileMap[folderPath] = p
				}
			} else {
				fileMap[filePath] = p
				fileMap[folderPath] = p
			}
		}
	}

	return fileMap, nil
}

func isDir(str string) bool {
	_, err := os.Stat(str)
	if err == nil {
		return true
	}
	if os.IsNotExist(err) {
		return false
	}
	return false
}
