// 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

	// mutex     sync.Mutex
	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
}
