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

import (
	"fmt"
	"path/filepath"
	"regexp"
	"strconv"

	"cuelang.org/go/cue"
	"cuelang.org/go/cue/ast"
	"cuelang.org/go/cue/ast/astutil"
	"cuelang.org/go/cue/build"
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/cue/parser"
	"cuelang.org/go/cue/token"
	"cuelang.org/go/encoding/protobuf/jsonpb"
	"cuelang.org/go/internal"
	"cuelang.org/go/internal/astinternal"
	"cuelang.org/go/internal/encoding"
)

// This file contains logic for placing orphan files within a CUE namespace.

func (b *buildPlan) usePlacement() bool {
	return b.perFile || b.useList || len(b.path) > 0
}

func (b *buildPlan) parsePlacementFlags() error {
	cmd := b.cmd
	b.perFile = flagFiles.Bool(cmd)
	b.useList = flagList.Bool(cmd)
	b.useContext = flagWithContext.Bool(cmd)

	for _, str := range flagPath.StringArray(cmd) {
		l, err := parser.ParseExpr("--path", str)
		if err != nil {
			labels, err := parseFullPath(str)
			if err != nil {
				return fmt.Errorf(
					`labels must be expressions (-l foo -l 'strings.ToLower(bar)') or full paths (-l '"foo": "\(strings.ToLower(bar))":) : %v`, err)
			}
			b.path = append(b.path, labels...)
			continue
		}

		b.path = append(b.path, &ast.ParenExpr{X: l})
	}

	if !b.importing && !b.perFile && !b.useList && len(b.path) == 0 {
		if b.useContext {
			return fmt.Errorf(
				"flag %q must be used with at least one of flag %q, %q, or %q",
				flagWithContext, flagPath, flagList, flagFiles,
			)
		}
	} else if b.schema != nil {
		return fmt.Errorf(
			"cannot combine --%s flag with flag %q, %q, or %q",
			flagSchema, flagPath, flagList, flagFiles,
		)
	}
	return nil
}

func (b *buildPlan) placeOrphans(i *build.Instance, a []*decoderInfo) error {
	pkg := b.encConfig.PkgName
	if pkg == "" {
		pkg = i.PkgName
	} else if pkg != "" && i.PkgName != "" && i.PkgName != pkg && !flagForce.Bool(b.cmd) {
		return fmt.Errorf(
			"%q flag clashes with existing package name (%s vs %s)",
			flagPackage, pkg, i.PkgName,
		)
	}

	var files []*ast.File

	re, err := regexp.Compile(b.cfg.fileFilter)
	if err != nil {
		return err
	}

	for _, di := range a {
		if !i.User && !re.MatchString(filepath.Base(di.file.Filename)) {
			continue
		}

		d := di.dec(b)

		var objs []*ast.File

		// Filter only need to filter files that can stream:
		for ; !d.Done(); d.Next() {
			if f := d.File(); f != nil {
				f.Filename = newName(d.Filename(), 0)
				objs = append(objs, f)
			}
		}
		if err := d.Err(); err != nil {
			return err
		}

		if b.perFile {
			for i, obj := range objs {
				f, err := placeOrphans(b, d, pkg, obj)
				if err != nil {
					return err
				}
				f.Filename = newName(d.Filename(), i)
				files = append(files, f)
			}
			continue
		}
		// TODO: consider getting rid of this requirement. It is important that
		// import will catch conflicts ahead of time then, though, and report
		// this messages as a possible solution if there are conflicts.
		if b.importing && len(objs) > 1 && len(b.path) == 0 && !b.useList {
			return fmt.Errorf(
				"%s, %s, or %s flag needed to handle multiple objects in file %s",
				flagPath, flagList, flagFiles, shortFile(i.Root, di.file))
		}

		if !b.useList && len(b.path) == 0 && !b.useContext {
			for _, f := range objs {
				if pkg := b.encConfig.PkgName; pkg != "" {
					internal.SetPackage(f, pkg, false)
				}
				files = append(files, f)
			}
		} else {
			// TODO: handle imports correctly, i.e. for proto.
			f, err := placeOrphans(b, d, pkg, objs...)
			if err != nil {
				return err
			}
			f.Filename = newName(d.Filename(), 0)
			files = append(files, f)
		}
	}

	b.imported = append(b.imported, files...)
	for _, f := range files {
		if err := i.AddSyntax(f); err != nil {
			return err
		}
	}
	return nil
}

func placeOrphans(b *buildPlan, d *encoding.Decoder, pkg string, objs ...*ast.File) (*ast.File, error) {
	f := &ast.File{}
	filename := d.Filename()

	index := newIndex()
	for i, file := range objs {
		if i == 0 {
			astutil.CopyMeta(f, file)
		}
		expr := internal.ToExpr(file)
		p, _, _ := internal.PackageInfo(file)

		var path cue.Path
		var labels []ast.Label

		switch {
		case len(b.path) > 0:
			expr := expr
			if b.useContext {
				expr = ast.NewStruct(
					"data", expr,
					"filename", ast.NewString(filename),
					"index", ast.NewLit(token.INT, strconv.Itoa(i)),
					"recordCount", ast.NewLit(token.INT, strconv.Itoa(len(objs))),
				)
			}
			var f *ast.File
			if s, ok := expr.(*ast.StructLit); ok {
				f = &ast.File{Decls: s.Elts}
			} else {
				f = &ast.File{Decls: []ast.Decl{&ast.EmbedDecl{Expr: expr}}}
			}
			err := astutil.Sanitize(f)
			if err != nil {
				return nil, errors.Wrapf(err, token.NoPos,
					"invalid combination of input files")
			}
			inst, err := runtime.CompileFile(f)
			if err != nil {
				return nil, err
			}

			var a []cue.Selector

			for _, label := range b.path {
				switch x := label.(type) {
				case *ast.Ident, *ast.BasicLit:
				case ast.Expr:
					if p, ok := x.(*ast.ParenExpr); ok {
						x = p.X // unwrap for better error messages
					}
					switch l := inst.Eval(x); l.Kind() {
					case cue.StringKind, cue.IntKind:
						label = l.Syntax().(ast.Label)

					default:
						var arg interface{} = l
						if err := l.Err(); err != nil {
							arg = err
						}
						return nil, fmt.Errorf(
							`error evaluating label %v: %v`,
							astinternal.DebugStr(x), arg)
					}
				}
				a = append(a, cue.Label(label))
				labels = append(labels, label)
			}

			path = cue.MakePath(a...)
		}

		switch d.Interpretation() {
		case build.ProtobufJSON:
			v := b.instance.Value().LookupPath(path)
			if b.useList {
				v, _ = v.Elem()
			}
			if !v.Exists() {
				break
			}
			if err := jsonpb.NewDecoder(v).RewriteFile(file); err != nil {
				return nil, err
			}
		}

		if b.useList {
			idx := index
			for _, e := range labels {
				idx = idx.label(e)
			}
			if idx.field.Value == nil {
				idx.field.Value = &ast.ListLit{
					Lbrack: token.NoSpace.Pos(),
					Rbrack: token.NoSpace.Pos(),
				}
			}
			list := idx.field.Value.(*ast.ListLit)
			list.Elts = append(list.Elts, expr)
		} else if len(labels) == 0 {
			obj, ok := expr.(*ast.StructLit)
			if !ok {
				if _, ok := expr.(*ast.ListLit); ok {
					return nil, fmt.Errorf("expected struct as object root, did you mean to use the --list flag?")
				}
				return nil, fmt.Errorf("cannot map non-struct to object root")
			}
			f.Decls = append(f.Decls, obj.Elts...)
		} else {
			field := &ast.Field{Label: labels[0]}
			f.Decls = append(f.Decls, field)
			if p != nil {
				astutil.CopyComments(field, p)
			}
			for _, e := range labels[1:] {
				newField := &ast.Field{Label: e}
				newVal := ast.NewStruct(newField)
				field.Value = newVal
				field = newField
			}
			field.Value = expr
		}
	}

	if pkg != "" {
		internal.SetPackage(f, pkg, false)
	}

	if b.useList {
		switch x := index.field.Value.(type) {
		case *ast.StructLit:
			f.Decls = append(f.Decls, x.Elts...)
		case *ast.ListLit:
			f.Decls = append(f.Decls, &ast.EmbedDecl{Expr: x})
		default:
			panic("unreachable")
		}
	}

	return f, astutil.Sanitize(f)
}

func parseFullPath(exprs string) (p []ast.Label, err error) {
	f, err := parser.ParseFile("--path", exprs+"_")
	if err != nil {
		return p, fmt.Errorf("parser error in path %q: %v", exprs, err)
	}

	if len(f.Decls) != 1 {
		return p, errors.New("path flag must be a space-separated sequence of labels")
	}

	for d := f.Decls[0]; ; {
		field, ok := d.(*ast.Field)
		if !ok {
			// This should never happen
			return p, errors.New("%q not a sequence of labels")
		}

		switch x := field.Label.(type) {
		case *ast.Ident, *ast.BasicLit:
			p = append(p, x)

		case ast.Expr:
			p = append(p, &ast.ParenExpr{X: x})

		default:
			return p, fmt.Errorf("unsupported label type %T", x)
		}

		v, ok := field.Value.(*ast.StructLit)
		if !ok {
			break
		}

		if len(v.Elts) != 1 {
			return p, errors.New("path value may not contain a struct")
		}

		d = v.Elts[0]
	}
	return p, nil
}

type listIndex struct {
	index map[string]*listIndex
	field *ast.Field
}

func newIndex() *listIndex {
	return &listIndex{
		index: map[string]*listIndex{},
		field: &ast.Field{},
	}
}

func (x *listIndex) label(label ast.Label) *listIndex {
	key := astinternal.DebugStr(label)
	idx := x.index[key]
	if idx == nil {
		if x.field.Value == nil {
			x.field.Value = &ast.StructLit{}
		}
		obj := x.field.Value.(*ast.StructLit)
		newField := &ast.Field{Label: label}
		obj.Elts = append(obj.Elts, newField)
		idx = &listIndex{
			index: map[string]*listIndex{},
			field: newField,
		}
		x.index[key] = idx
	}
	return idx
}

func newName(filename string, i int) string {
	if filename == "-" {
		return filename
	}
	ext := filepath.Ext(filename)
	filename = filename[:len(filename)-len(ext)]
	if i > 0 {
		filename += fmt.Sprintf("-%d", i)
	}
	filename += ".cue"
	return filename
}
