// Copyright 2020 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 checklicenses

import (
	"context"
	"errors"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"runtime/trace"
	"sort"
	"sync"
)

// Licenses is an object that facilitates operations on each License object in bulk.
type Licenses struct {
	licenses []*License
	notices  []*License

	sync.RWMutex
}

// NewLicenses returns a Licenses object with each license pattern loaded from
// the .lic folder location specified in the config file.
func NewLicenses(ctx context.Context, config *Config) (*Licenses, error) {
	defer trace.StartRegion(ctx, "NewLicenses").End()

	l := &Licenses{}
	err := filepath.Walk(config.LicensePatternDir,
		func(path string, info os.FileInfo, err error) error {
			if info.IsDir() {
				return nil
			}
			license, err := NewLicense(path, config)
			if err != nil {
				return err
			}
			l.licenses = append(l.licenses, license)
			return nil
		})
	if err != nil {
		return nil, err
	}

	if len(l.licenses) == 0 {
		return nil, errors.New("no licenses")
	}

	sort.Sort(licenseByPattern(l.licenses))

	return l, nil
}

func (l *Licenses) GetFilesWithProhibitedLicenses() []string {
	var filesWithProhibitedLicenses []string
	set := map[string]bool{}
	for _, license := range l.licenses {
		if license.ValidType {
			continue
		}
		for _, match := range license.matches {
			for _, path := range match.Files {
				if !contains(license.AllowedDirs, path) {
					log.Printf("Prohibited: %q in %q\n", license.Category, path)
					if _, found := set[path]; !found {
						set[path] = true
						filesWithProhibitedLicenses = append(filesWithProhibitedLicenses, path)
					}
				}
			}
		}
	}

	sort.Strings(filesWithProhibitedLicenses)
	return filesWithProhibitedLicenses
}

func (l *Licenses) GetFilesWithBadLicenseUsage() []string {
	var filesWithBadLicenseUsage []string
	set := map[string]bool{}
	for _, license := range l.licenses {
		if len(license.BadLicenseUsage) > 0 {
			for _, path := range license.BadLicenseUsage {
				log.Printf("Not allowlisted: %q in %q\n", license.Category, path)
				if _, found := set[path]; !found {
					set[path] = true
					filesWithBadLicenseUsage = append(filesWithBadLicenseUsage, path)
				}
			}
		}
	}

	sort.Strings(filesWithBadLicenseUsage)
	return filesWithBadLicenseUsage
}

func (l *Licenses) MatchSingleLicenseFile(data []byte, path string, metrics *Metrics, ft *FileTree) {
	for _, license := range l.licenses {
		if ok, match := license.Search(data, path); ok {
			metrics.increment("num_single_license_file_match")
			ft.Lock()
			ft.SingleLicenseFiles[path] = append(ft.SingleLicenseFiles[path], license)
			ft.LicenseMatches[path] = append(ft.LicenseMatches[path], match)
			ft.Unlock()
		}
	}
}

func (l *Licenses) MatchNoticeFile(data []byte, path string, metrics *Metrics, ft *FileTree) {
	custom := NewCustomLicense(path)
	l.Lock()
	l.notices = append(l.notices, custom)
	l.Unlock()

	if ok, match := custom.Search(data, path); ok {
		metrics.increment("num_single_license_file_match")
		ft.Lock()
		ft.SingleLicenseFiles[path] = append(ft.SingleLicenseFiles[path], custom)
		ft.LicenseMatches[path] = append(ft.LicenseMatches[path], match)
		ft.Unlock()
	} else {
		fmt.Printf("Error: failed to match custom license text '%v'\n", path)
	}
}

// MatchFile returns true if any License matches input data
// along with the license that matched. It returns false and nil
// if there were no matches.
func (l *Licenses) MatchFile(data []byte, path string, metrics *Metrics) (bool, *License, *Match) {
	for _, license := range l.licenses {
		if ok, match := license.Search(data, path); ok {
			metrics.increment("num_licensed")
			return true, license, match
		}
	}
	return false, nil, nil
}
