// Copyright 2023 The Bazel Authors. All rights reserved.
//
// Licensed 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 python

import (
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/bazelbuild/bazel-gazelle/config"
	"github.com/bazelbuild/bazel-gazelle/rule"

	"github.com/bazelbuild/rules_python/gazelle/manifest"
	"github.com/bazelbuild/rules_python/gazelle/pythonconfig"
)

// Configurer satisfies the config.Configurer interface. It's the
// language-specific configuration extension.
type Configurer struct{}

// RegisterFlags registers command-line flags used by the extension. This
// method is called once with the root configuration when Gazelle
// starts. RegisterFlags may set an initial values in Config.Exts. When flags
// are set, they should modify these values.
func (py *Configurer) RegisterFlags(fs *flag.FlagSet, cmd string, c *config.Config) {}

// CheckFlags validates the configuration after command line flags are parsed.
// This is called once with the root configuration when Gazelle starts.
// CheckFlags may set default values in flags or make implied changes.
func (py *Configurer) CheckFlags(fs *flag.FlagSet, c *config.Config) error {
	return nil
}

// KnownDirectives returns a list of directive keys that this Configurer can
// interpret. Gazelle prints errors for directives that are not recoginized by
// any Configurer.
func (py *Configurer) KnownDirectives() []string {
	return []string{
		pythonconfig.PythonExtensionDirective,
		pythonconfig.PythonRootDirective,
		pythonconfig.PythonManifestFileNameDirective,
		pythonconfig.IgnoreFilesDirective,
		pythonconfig.IgnoreDependenciesDirective,
		pythonconfig.ValidateImportStatementsDirective,
		pythonconfig.GenerationMode,
		pythonconfig.GenerationModePerFileIncludeInit,
		pythonconfig.LibraryNamingConvention,
		pythonconfig.BinaryNamingConvention,
		pythonconfig.TestNamingConvention,
		pythonconfig.DefaultVisibilty,
		pythonconfig.Visibility,
	}
}

// Configure modifies the configuration using directives and other information
// extracted from a build file. Configure is called in each directory.
//
// c is the configuration for the current directory. It starts out as a copy
// of the configuration for the parent directory.
//
// rel is the slash-separated relative path from the repository root to
// the current directory. It is "" for the root directory itself.
//
// f is the build file for the current directory or nil if there is no
// existing build file.
func (py *Configurer) Configure(c *config.Config, rel string, f *rule.File) {
	// Create the root config.
	if _, exists := c.Exts[languageName]; !exists {
		rootConfig := pythonconfig.New(c.RepoRoot, "")
		c.Exts[languageName] = pythonconfig.Configs{"": rootConfig}
	}

	configs := c.Exts[languageName].(pythonconfig.Configs)

	config, exists := configs[rel]
	if !exists {
		parent := configs.ParentForPackage(rel)
		config = parent.NewChild()
		configs[rel] = config
	}

	if f == nil {
		return
	}

	gazelleManifestFilename := "gazelle_python.yaml"

	for _, d := range f.Directives {
		switch d.Key {
		case "exclude":
			// We record the exclude directive for coarse-grained packages
			// since we do manual tree traversal in this mode.
			config.AddExcludedPattern(filepath.Join(rel, strings.TrimSpace(d.Value)))
		case pythonconfig.PythonExtensionDirective:
			switch d.Value {
			case "enabled":
				config.SetExtensionEnabled(true)
			case "disabled":
				config.SetExtensionEnabled(false)
			default:
				err := fmt.Errorf("invalid value for directive %q: %s: possible values are enabled/disabled",
					pythonconfig.PythonExtensionDirective, d.Value)
				log.Fatal(err)
			}
		case pythonconfig.PythonRootDirective:
			config.SetPythonProjectRoot(rel)
			config.SetDefaultVisibility([]string{fmt.Sprintf(pythonconfig.DefaultVisibilityFmtString, rel)})
		case pythonconfig.PythonManifestFileNameDirective:
			gazelleManifestFilename = strings.TrimSpace(d.Value)
		case pythonconfig.IgnoreFilesDirective:
			for _, ignoreFile := range strings.Split(d.Value, ",") {
				config.AddIgnoreFile(ignoreFile)
			}
		case pythonconfig.IgnoreDependenciesDirective:
			for _, ignoreDependency := range strings.Split(d.Value, ",") {
				config.AddIgnoreDependency(ignoreDependency)
			}
		case pythonconfig.ValidateImportStatementsDirective:
			v, err := strconv.ParseBool(strings.TrimSpace(d.Value))
			if err != nil {
				log.Fatal(err)
			}
			config.SetValidateImportStatements(v)
		case pythonconfig.GenerationMode:
			switch pythonconfig.GenerationModeType(strings.TrimSpace(d.Value)) {
			case pythonconfig.GenerationModePackage:
				config.SetCoarseGrainedGeneration(false)
				config.SetPerFileGeneration(false)
			case pythonconfig.GenerationModeFile:
				config.SetCoarseGrainedGeneration(false)
				config.SetPerFileGeneration(true)
			case pythonconfig.GenerationModeProject:
				config.SetCoarseGrainedGeneration(true)
				config.SetPerFileGeneration(false)
			default:
				err := fmt.Errorf("invalid value for directive %q: %s",
					pythonconfig.GenerationMode, d.Value)
				log.Fatal(err)
			}
		case pythonconfig.GenerationModePerFileIncludeInit:
			v, err := strconv.ParseBool(strings.TrimSpace(d.Value))
			if err != nil {
				log.Fatal(err)
			}
			config.SetPerFileGenerationIncludeInit(v)
		case pythonconfig.LibraryNamingConvention:
			config.SetLibraryNamingConvention(strings.TrimSpace(d.Value))
		case pythonconfig.BinaryNamingConvention:
			config.SetBinaryNamingConvention(strings.TrimSpace(d.Value))
		case pythonconfig.TestNamingConvention:
			config.SetTestNamingConvention(strings.TrimSpace(d.Value))
		case pythonconfig.DefaultVisibilty:
			switch directiveArg := strings.TrimSpace(d.Value); directiveArg {
			case "NONE":
				config.SetDefaultVisibility([]string{})
			case "DEFAULT":
				pythonProjectRoot := config.PythonProjectRoot()
				defaultVisibility := fmt.Sprintf(pythonconfig.DefaultVisibilityFmtString, pythonProjectRoot)
				config.SetDefaultVisibility([]string{defaultVisibility})
			default:
				// Handle injecting the python root. Assume that the user used the
				// exact string "$python_root".
				labels := strings.ReplaceAll(directiveArg, "$python_root", config.PythonProjectRoot())
				config.SetDefaultVisibility(strings.Split(labels, ","))
			}
		case pythonconfig.Visibility:
			config.AppendVisibility(strings.TrimSpace(d.Value))
		}
	}

	gazelleManifestPath := filepath.Join(c.RepoRoot, rel, gazelleManifestFilename)
	gazelleManifest, err := py.loadGazelleManifest(gazelleManifestPath)
	if err != nil {
		log.Fatal(err)
	}
	if gazelleManifest != nil {
		config.SetGazelleManifest(gazelleManifest)
	}
}

func (py *Configurer) loadGazelleManifest(gazelleManifestPath string) (*manifest.Manifest, error) {
	if _, err := os.Stat(gazelleManifestPath); err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, fmt.Errorf("failed to load Gazelle manifest at %q: %w", gazelleManifestPath, err)
	}
	manifestFile := new(manifest.File)
	if err := manifestFile.Decode(gazelleManifestPath); err != nil {
		return nil, fmt.Errorf("failed to load Gazelle manifest at %q: %w", gazelleManifestPath, err)
	}
	return manifestFile.Manifest, nil
}
