// Copyright 2023 The Shac Authors
//
// 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 engine

import (
	"context"
	"errors"
	"fmt"
	"strings"

	"go.chromium.org/luci/starlark/builtins"
	"go.starlark.net/lib/json"
	"go.starlark.net/starlark"
	"go.starlark.net/starlarkstruct"
)

// getPredeclared returns the predeclared starlark symbols in the runtime.
//
// The upstream starlark interpreter includes all the symbols described at
// https://github.com/google/starlark-go/blob/HEAD/doc/spec.md#built-in-constants-and-functions
// See https://pkg.go.dev/go.starlark.net/starlark#Universe for the default list.
func getPredeclared() starlark.StringDict {
	return starlark.StringDict{
		"shac": toValue("shac", getShac()),

		// Add https://bazel.build/rules/lib/json so it feels more natural to bazel
		// users.
		"json": json.Module,

		// Override fail to include additional functionality.
		//
		// Do not use newBuiltinNone() because it needs access to the thread to
		// capture the stack trace.
		"fail": starlark.NewBuiltin("fail", fail),
		// struct is an helper function that enables users to create seamless
		// object instances.
		"struct": builtins.Struct,
	}
}

// fail aborts execution. When run within a check, associates the check with an "abnormal failure".
//
// Unlike builtins.Fail(), it doesn't allow user specified stack traces.
func fail(th *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
	sep := " "
	// Do not exit early if the arguments are wrong.
	err := starlark.UnpackArgs(fn.Name(), nil, kwargs, "sep?", &sep)
	buf := strings.Builder{}
	for i, v := range args {
		if i > 0 {
			buf.WriteString(sep)
		}
		if s, ok := starlark.AsString(v); ok {
			buf.WriteString(s)
		} else {
			buf.WriteString(v.String())
		}
	}
	if err != nil {
		buf.WriteString("\n")
		buf.WriteString(err.Error())
	}
	msg := buf.String()
	failErr := &failure{
		Message: msg,
		Stack:   th.CallStack(),
	}
	ctx := getContext(th)
	if c := ctxCheck(ctx); c != nil {
		// Running inside a check, annotate it.
		c.failErr = failErr
	} else {
		// Save the error in the shacState object since we are in the first phase.
		s := ctxShacState(ctx)
		s.failErr = failErr
	}
	return nil, errors.New(fn.Name() + ": " + msg)
}

// toValue converts a StringDict to a Value.
func toValue(name string, d starlark.StringDict) starlark.Value {
	return starlarkstruct.FromStringDict(starlark.String(name), d)
}

type builtin func(ctx context.Context, s *shacState, name string, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error)
type boundBuiltin func(ctx context.Context, s *shacState, name string, self starlark.Value, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error)

// newBuiltin registers a go function as a Starlark builtin.
//
// It's identical to `starlark.NewBuiltin()`, but prepends the function name to
// the text of any returned errors as a usability improvement.
func newBuiltin(name string, impl builtin) *starlark.Builtin {
	return starlark.NewBuiltin(name, func(th *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
		return builtinWrapper(th, name, func(ctx context.Context, s *shacState) (starlark.Value, error) {
			return impl(ctx, s, name, args, kwargs)
		})
	})
}

// newBoundBuiltin registers a go function as a Starlark builtin that's bound to
// an object.
//
// The method receiver is passed to `impl` as an argument.
func newBoundBuiltin(name string, impl boundBuiltin) *starlark.Builtin {
	return starlark.NewBuiltin(name, func(th *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
		return builtinWrapper(th, name, func(ctx context.Context, s *shacState) (starlark.Value, error) {
			self := fn.Receiver()
			return impl(ctx, s, name, self, args, kwargs)
		})
	})
}

func builtinWrapper(th *starlark.Thread, name string, f func(ctx context.Context, s *shacState) (starlark.Value, error)) (starlark.Value, error) {
	ctx := getContext(th)
	s := ctxShacState(ctx)
	val, err := f(ctx, s)
	if err != nil {
		// starlark.UnpackArgs already adds the function name prefix to errors
		// it returns, so make sure not to duplicate the prefix if it's already
		// there.
		if !strings.HasPrefix(err.Error(), name+": ") {
			err = fmt.Errorf("%s: %w", name, err)
		}
		return nil, err
	}
	// All values returned by builtins are immutable. This is not a hard
	// requirement, and can be relaxed if there's a use case for mutable
	// return values, but it's still a sensible default.
	val.Freeze()
	return val, nil
}

func newBuiltinNone(name string, f func(ctx context.Context, s *shacState, name string, args starlark.Tuple, kwargs []starlark.Tuple) error) *starlark.Builtin {
	return newBuiltin(
		name,
		func(ctx context.Context, s *shacState, name string, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
			return starlark.None, f(ctx, s, name, args, kwargs)
		})
}
