// Copyright 2020 The Monogon Project Authors.
//
// SPDX-License-Identifier: Apache-2.0
//
// 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 main

import (
	"fmt"
)

// The Planner provides the main DSL and high-level control logic for resolving dependencies. It is the main API that
// fietsje users should consume.

// planner is a builder for a single world of Go package dependencies, and what is then emitted into a Starlark file
// containing gazelle go_repository rules.
// The planner's builder system covers three increasingly specific contextx:
//  - planner (this structure, allows for 'collecting' in high-level dependencies. ie. collections)
//  - collection (represents what has been pulled in by a high-level dependency, and allows for 'using' transitive
//    dependencies from a collection)
//  - optionized (represents a collection with extra build flags, eg. disabled proto builds)
type planner struct {
	// available is a map of importpaths to dependencies that the planner knows. This is a flat structure that is the
	// main source of truth of actual dependency data, like a registry of everything that the planner knows about.
	// The available dependency for a given importpath, as the planner progresses, might change, ie. when there is a
	// version conflict. As such, code should use importpaths as atoms describing dependencies, instead of holding
	// dependency pointers.
	available map[string]*dependency
	// enabled is a map of dependencies that will be emitted by the planner into the build via Gazelle.
	enabled map[string]bool
	// seen is a map of 'dependency' -> 'parent' importpaths, ie. returns what higher-level dependency (ie. one enabled
	// with .collect()) pulled in a given dependency. This is only used for error messages to help the user find what
	// a transitive  dependency has been pulled in by.
	seen map[string]string

	shelf *shelf
}

func (p *planner) collect(importpath, version string, opts ...buildOpt) *collection {
	return p.collectInternal(importpath, version, false, opts...)
}

func (p *planner) collectOverride(importpath, version string, opts ...buildOpt) *collection {
	return p.collectInternal(importpath, version, true, opts...)
}

// collectInternal pulls in a high-level dependency into the planner and
// enables it. It also parses all of its transitive // dependencies (not just
// directly transitive, but recursively transitive) and makes the planner aware
// of them. It does not enable these transitive dependencies, but returns a
// collection builder, which can be used to do se by calling .use().
func (p *planner) collectInternal(importpath, version string, override bool, opts ...buildOpt) *collection {
	// Ensure overrides are explicit and minimal.
	by, ok := p.seen[importpath]
	if ok && !override {
		panic(fmt.Errorf("%s is being collected, but has already been declared by %s; replace it by a use(%q) call on %s or use collectOverride", importpath, by, importpath, by))
	}
	if !ok && override {
		panic(fmt.Errorf("%s is being collected with override, but has not been seen as a dependency previously - use .collect(%q, %q) instead", importpath, importpath, version))
	}

	d := &dependency{
		shelf:      p.shelf,
		importpath: importpath,
		version:    version,
	}
	for _, o := range opts {
		o(d)
	}

	// automatically enable direct import
	p.enabled[d.importpath] = true
	p.available[d.importpath] = d

	td, err := d.getTransitiveDeps()
	if err != nil {
		panic(fmt.Errorf("could not get transitive deps for %q: %v", d.importpath, err))
	}
	// add transitive deps to 'available' map
	for k, v := range td {
		// skip dependencies that have already been enabled, dependencies are 'first enabled version wins'.
		if _, ok := p.available[k]; ok && p.enabled[k] {
			continue
		}

		p.available[k] = v

		// make note of the high-level dependency that pulled in the dependency.
		p.seen[v.importpath] = d.importpath
	}

	return &collection{
		p:          p,
		highlevel:  d,
		transitive: td,
	}
}

// collection represents the context of the planner after pulling/collecting in a high-level dependency. In this state,
// the planner can be used to enable transitive dependencies of the high-level dependency.
type collection struct {
	p *planner

	highlevel  *dependency
	transitive map[string]*dependency
}

// use enables given dependencies defined in the collection by a high-level dependency.
func (c *collection) use(paths ...string) *collection {
	return c.with().use(paths...)
}

// inject adds a dependency to a collection as if requested by the high-level dependency of the collection. This should
// be used sparingly, for instance when high-level dependencies contain bazel code that uses some external workspaces
// from Go modules, and those workspaces are not defined in parsed transitive dependency definitions like go.mod/sum.
func (c *collection) inject(importpath, version string) *collection {
	d := c.highlevel.child(importpath, version)
	c.transitive[importpath] = d
	c.p.available[importpath] = d
	c.p.enabled[importpath] = true

	return c
}

// with transforms a collection into an optionized, by setting some build options.
func (c *collection) with(o ...buildOpt) *optionized {
	return &optionized{
		c:    c,
		opts: o,
	}
}

// optionized is a collection that has some build options set, that will be applied to all dependencies 'used' in this
// context
type optionized struct {
	c    *collection
	opts []buildOpt
}

// buildOpt is a build option passed to Gazelle.
type buildOpt func(d *dependency)

// buildTags sets the given buildTags in affected dependencies.
func buildTags(tags ...string) buildOpt {
	return func(d *dependency) {
		d.buildTags = tags
	}
}

// disabledProtoBuild disables protobuf builds in affected dependencies.
func disabledProtoBuild(d *dependency) {
	d.disableProtoBuild = true
}

// patches applies patches in affected dependencies after BUILD file generation.
func patches(patches ...string) buildOpt {
	return func(d *dependency) {
		d.patches = patches
	}
}

// use enables given dependencies defined in the collection by a high-level dependency, with any set build options.
// After returning, the builder degrades to a collection - ie, all build options are reset.
func (o *optionized) use(paths ...string) *collection {
	for _, path := range paths {
		el, ok := o.c.transitive[path]
		if !ok {
			msg := fmt.Sprintf("dependency %q not found in %q", path, o.c.highlevel.importpath)
			if alternative, ok := o.c.p.seen[path]; ok {
				msg += fmt.Sprintf(" (but found in %q)", alternative)
			} else {
				msg += " or any other collected library"
			}
			panic(msg)
		}
		for _, o := range o.opts {
			o(el)
		}
		o.c.p.enabled[path] = true
	}

	return o.c
}
