// 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 (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"strings"

	"go.fuchsia.dev/fuchsia/tools/check-licenses/file"
	"go.fuchsia.dev/fuchsia/tools/check-licenses/filetree"
	"go.fuchsia.dev/fuchsia/tools/check-licenses/license"
	"go.fuchsia.dev/fuchsia/tools/check-licenses/project"
	"go.fuchsia.dev/fuchsia/tools/check-licenses/result"
	"go.fuchsia.dev/fuchsia/tools/check-licenses/result/world"
)

var (
	ConfigVars map[string]string
)

func init() {
	ConfigVars = make(map[string]string)
}

type Include struct {
	Path     []string `json:"paths"`
	Notes    []string `json:"notes"`
	Required bool     `json:"required"`
}

type CheckLicensesConfig struct {
	LogLevel int    `json:"logLevel"`
	OutDir   string `json:"outDir"`

	Includes []Include `json:"includes"`

	File     *file.FileConfig         `json:"file"`
	License  *license.LicenseConfig   `json:"license"`
	Project  *project.ProjectConfig   `json:"project"`
	FileTree *filetree.FileTreeConfig `json:"filetree"`
	Result   *result.ResultConfig     `json:"result"`
	World    *world.WorldConfig       `json:"world"`

	Target string `json:"target"`
}

func NewCheckLicensesConfig(path string) (*CheckLicensesConfig, error) {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("Failed to read config file [%v]: %w\n", path, err)
	}

	c, err := NewCheckLicensesConfigJson(string(b))
	if err != nil {
		return nil, fmt.Errorf("Failed to parse JSON config file [%v]: %v\n", path, err)
	}
	return c, nil
}

func NewCheckLicensesConfigJson(configJson string) (*CheckLicensesConfig, error) {
	for k, v := range ConfigVars {
		configJson = strings.ReplaceAll(configJson, k, v)
	}

	// Make sure all variables have been replaced.
	r := regexp.MustCompile(`({[\w]+})`)
	matches := r.FindAllStringSubmatch(configJson, -1)

	if len(matches) > 0 {
		return nil, fmt.Errorf("Found unexpanded variable(s) in config file: %v\n", configJson)
	}

	c := &CheckLicensesConfig{
		File:     file.NewConfig(),
		License:  license.NewConfig(),
		Project:  project.NewConfig(),
		FileTree: filetree.NewConfig(),
		Result:   result.NewConfig(),
		World:    world.NewConfig(),
	}

	d := json.NewDecoder(strings.NewReader(configJson))
	// TODO: Uncomment once "Filter" fields are removed from all config files.
	//d.DisallowUnknownFields()
	if err := d.Decode(c); err != nil {
		return nil, err
	}

	// Loop over the Includes field and merge in all config files
	// from that list, recursively.
	if len(c.Includes) > 0 {
		for _, include := range c.Includes {
			for _, path := range include.Path {
				c2, err := NewCheckLicensesConfig(path)
				// If we get an error loading the config file,
				// it may be because a given submodule isn't
				// available on your machine (e.g. //vendor/google).
				//
				// Only error out if this config section is marked
				// as "required".
				if err != nil {
					if errors.Is(err, os.ErrNotExist) && !include.Required {
						if c.LogLevel > 0 {
							log.Printf("Failed to create config file for %s: %v.\n", path, err)
						}
						continue
					} else {
						return nil, err
					}
				}
				c.Merge(c2)
			}
		}
	}

	return c, nil
}

func (c *CheckLicensesConfig) Merge(other *CheckLicensesConfig) error {
	c.File.Merge(other.File)
	c.License.Merge(other.License)
	c.FileTree.Merge(other.FileTree)
	c.Project.Merge(other.Project)
	c.Result.Merge(other.Result)
	c.World.Merge(other.World)

	c.Includes = append(c.Includes, other.Includes...)
	if c.OutDir == "" {
		c.OutDir = other.OutDir
	}
	if other.LogLevel > c.LogLevel {
		c.LogLevel = other.LogLevel
	}

	return nil
}
