// Copyright 2020 CUE 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 runtime

import (
	"path"
	"sync"

	"cuelang.org/go/cue/build"
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/internal/core/adt"
)

type PackageFunc func(ctx adt.Runtime) (*adt.Vertex, errors.Error)

func RegisterBuiltin(importPath string, f PackageFunc) {
	sharedIndex.RegisterBuiltin(importPath, f)
}

func (x *index) RegisterBuiltin(importPath string, f PackageFunc) {
	if x.builtinPaths == nil {
		x.builtinPaths = map[string]PackageFunc{}
		x.builtinShort = map[string]string{}
	}
	x.builtinPaths[importPath] = f
	base := path.Base(importPath)
	if _, ok := x.builtinShort[base]; ok {
		importPath = "" // Don't allow ambiguous base paths.
	}
	x.builtinShort[base] = importPath
}

var SharedRuntime = &Runtime{index: sharedIndex}

// BuiltinPackagePath converts a short-form builtin package identifier to its
// full path or "" if this doesn't exist.
func (x *Runtime) BuiltinPackagePath(path string) string {
	return x.index.shortBuiltinToPath(path)
}

// sharedIndex is used for indexing builtins and any other labels common to
// all instances.
var sharedIndex = newIndex()

// index maps conversions from label names to internal codes.
//
// All instances belonging to the same package should share this index.
type index struct {
	// Change this to Instance at some point.
	// From *structLit/*Vertex -> Instance
	imports        map[*adt.Vertex]*build.Instance
	importsByPath  map[string]*adt.Vertex
	importsByBuild map[*build.Instance]*adt.Vertex
	builtinPaths   map[string]PackageFunc // Full path
	builtinShort   map[string]string      // Commandline shorthand

	typeCache sync.Map // map[reflect.Type]evaluated
}

func newIndex() *index {
	i := &index{
		imports:        map[*adt.Vertex]*build.Instance{},
		importsByPath:  map[string]*adt.Vertex{},
		importsByBuild: map[*build.Instance]*adt.Vertex{},
	}
	return i
}

func (x *index) shortBuiltinToPath(id string) string {
	if x == nil || x.builtinPaths == nil {
		return ""
	}
	return x.builtinShort[id]
}

func (r *Runtime) AddInst(path string, key *adt.Vertex, p *build.Instance) {
	x := r.index
	if key == nil {
		panic("key must not be nil")
	}
	x.imports[key] = p
	x.importsByBuild[p] = key
	if path != "" {
		x.importsByPath[path] = key
	}
}

func (r *Runtime) GetInstanceFromNode(key *adt.Vertex) *build.Instance {
	return r.index.imports[key]
}

func (r *Runtime) getNodeFromInstance(key *build.Instance) *adt.Vertex {
	return r.index.importsByBuild[key]
}

func (r *Runtime) LoadImport(importPath string) (*adt.Vertex, errors.Error) {
	x := r.index

	key := x.importsByPath[importPath]
	if key != nil {
		return key, nil
	}

	if x.builtinPaths != nil {
		if f := x.builtinPaths[importPath]; f != nil {
			p, err := f(r)
			if err != nil {
				return adt.ToVertex(&adt.Bottom{Err: err}), nil
			}
			inst := &build.Instance{
				ImportPath: importPath,
				PkgName:    path.Base(importPath),
			}
			x.imports[p] = inst
			x.importsByPath[importPath] = p
			x.importsByBuild[inst] = p
			return p, nil
		}
	}

	return key, nil
}
