//
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
package deps

import (
	"context"
	"fmt"
	"go/build"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"golang.org/x/mod/modfile"
	"golang.org/x/tools/go/packages"

	"github.com/apache/skywalking-eyes/license-eye/internal/logger"
	"github.com/apache/skywalking-eyes/license-eye/pkg/license"
)

type GoModResolver struct {
	Resolver
}

func (resolver *GoModResolver) CanResolve(file string) bool {
	base := filepath.Base(file)
	logger.Log.Debugln("Base name:", base)
	return base == "go.mod"
}

// Resolve resolves licenses of all dependencies declared in the go.mod file.
func (resolver *GoModResolver) Resolve(goModFile string, report *Report) error {
	content, err := ioutil.ReadFile(goModFile)
	if err != nil {
		return err
	}

	file, err := modfile.Parse(goModFile, content, nil)
	if err != nil {
		return err
	}

	logger.Log.Debugln("Resolving module:", file.Module.Mod)

	if err := os.Chdir(filepath.Dir(goModFile)); err != nil {
		return err
	}

	requiredPkgNames := make([]string, len(file.Require))
	for i, require := range file.Require {
		requiredPkgNames[i] = require.Mod.Path
	}

	logger.Log.Debugln("Required packages:", requiredPkgNames)

	if err := resolver.ResolvePackages(requiredPkgNames, report); err != nil {
		return err
	}

	return nil
}

// ResolvePackages resolves the licenses of the given packages.
func (resolver *GoModResolver) ResolvePackages(pkgNames []string, report *Report) error {
	requiredPkgs, err := packages.Load(&packages.Config{
		Context: context.Background(),
		Mode:    packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedDeps,
	}, pkgNames...)

	if err != nil {
		return err
	}

	packages.Visit(requiredPkgs, func(p *packages.Package) bool {
		if isBuiltIn(p) {
			logger.Log.Debugln("Built-in package doesn't require license check:", p.PkgPath)
			return false
		}

		if len(p.Errors) > 0 {
			logger.Log.Warnln("Failed to visit package:", p.PkgPath, p.Errors)
			report.Skip(&Result{
				Dependency:    p.PkgPath,
				LicenseSpdxID: Unknown,
			})
			return true
		}
		err := resolver.ResolvePackageLicense(p, report)
		if err != nil {
			logger.Log.Warnln("Failed to resolve the license of dependency:", p.PkgPath, err)
			report.Skip(&Result{
				Dependency:    p.PkgPath,
				LicenseSpdxID: Unknown,
			})
		}
		return true
	}, nil)

	return nil
}

var possibleLicenseFileName = regexp.MustCompile(`(?i)^LICENSE|LICENCE(\.txt)?$`)

func (resolver *GoModResolver) ResolvePackageLicense(p *packages.Package, report *Report) error {
	var filesInPkg []string
	if len(p.GoFiles) > 0 {
		filesInPkg = p.GoFiles
	} else if len(p.CompiledGoFiles) > 0 {
		filesInPkg = p.CompiledGoFiles
	} else if len(p.OtherFiles) > 0 {
		filesInPkg = p.OtherFiles
	}

	if len(filesInPkg) == 0 {
		return fmt.Errorf("empty package")
	}

	absPath, err := filepath.Abs(filesInPkg[0])
	if err != nil {
		return err
	}
	dir := filepath.Dir(absPath)

	for {
		files, err := ioutil.ReadDir(dir)
		if err != nil {
			return err
		}
		for _, info := range files {
			if !possibleLicenseFileName.MatchString(info.Name()) {
				continue
			}
			licenseFilePath := filepath.Join(dir, info.Name())
			content, err := ioutil.ReadFile(licenseFilePath)
			if err != nil {
				return err
			}
			identifier, err := license.Identify(p.PkgPath, string(content))
			if err != nil {
				return err
			}
			report.Resolve(&Result{
				Dependency:      p.PkgPath,
				LicenseFilePath: licenseFilePath,
				LicenseContent:  string(content),
				LicenseSpdxID:   identifier,
			})
			return nil
		}
		if resolver.shouldStopAt(dir) {
			break
		}
		dir = filepath.Dir(dir)
	}
	return nil
}

func (resolver *GoModResolver) shouldStopAt(dir string) bool {
	for _, srcDir := range build.Default.SrcDirs() {
		if srcDir == dir {
			return true
		}
	}
	return false
}

func isBuiltIn(pkg *packages.Package) bool {
	return len(pkg.GoFiles) > 0 && strings.HasPrefix(pkg.GoFiles[0], build.Default.GOROOT)
}
