// 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"
	"os"
	"path/filepath"
	"runtime/trace"
	"sort"
	"strings"
)

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

// NewLicenses returns a Licenses object with each license pattern loaded from
// the .lic folder location specified in Config
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 _, found := set[path]; !found && !contains(license.AllowedDirs, path) {
					set[path] = true
					filesWithProhibitedLicenses = append(filesWithProhibitedLicenses, path)
				}
			}
		}
	}
	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 {
				if _, found := set[path]; !found {
					set[path] = true
					filesWithBadLicenseUsage = append(filesWithBadLicenseUsage, path)
				}
			}
		}
	}
	return filesWithBadLicenseUsage
}

func CheckLicenseAllowList(license *License, path string) bool {
	var licenseAllowed = true
	if len(license.AllowedDirs) > 0 && !contains(license.AllowedDirs, path) {
		license.BadLicenseUsage = append(license.BadLicenseUsage, path)
		licenseAllowed = false
	}
	return licenseAllowed
}

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

// 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) {
	for _, license := range l.licenses {
		if license.Search(data, path) && CheckLicenseAllowList(license, path) {
			metrics.increment("num_licensed")
			return true, license
		}
	}
	return false, nil
}

func contains(matches []string, item string) bool {
	for _, m := range matches {
		if strings.Contains(item, m) {
			return true
		}
	}
	return false
}
