// Copyright 2021 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 cue

import (
	"bytes"
	"fmt"
	"math/big"

	"cuelang.org/go/cue/ast"
	"cuelang.org/go/cue/format"
	"cuelang.org/go/internal/core/export"
)

// TODO:
// * allow '-' to strip outer curly braces?
//     -    simplify output; can be used in combination with other flags
// * advertise:
//     c    like v, but print comments
//     a    like c, but print attributes and package-local hidden fields as well

// Format prints a CUE value.
//
// WARNING:
//     although we are narrowing down the semantics, the verbs and options
//     are still subject to change. this API is experimental although it is
//     likely getting close to the final design.
//
// It recognizes the following verbs:
//
//     v    print CUE value
//
// The verbs support the following flags:
//     #    print as schema and include definitions.
//          The result is printed as a self-contained file, instead of an the
//          expression format.
//     +    evaluate: resolve defaults and error on incomplete errors
//
// Indentation can be controlled as follows:
//     width      indent the cue block by <width> tab stops (e.g. %2v)
//     precision  convert tabs to <precision> spaces (e.g. %.2v), where
//                a value of 0 means no indentation or newlines (TODO).
//
// If the value kind corresponds to one of the following Go types, the
// usual Go formatting verbs for that type can be used:
//
//     Int:          b,d,o,O,q,x,X
//     Float:        f,e,E,g,G
//     String/Bytes: s,q,x,X
//
// The %v directive will be used if the type is not supported for that verb.
//
func (v Value) Format(state fmt.State, verb rune) {
	if v.v == nil {
		fmt.Fprint(state, "<nil>")
		return
	}

	switch verb {
	case 'a':
		formatCUE(state, v, true, true)
	case 'c':
		formatCUE(state, v, true, false)
	case 'v':
		formatCUE(state, v, false, false)

	case 'd', 'o', 'O', 'U':
		var i big.Int
		if _, err := v.Int(&i); err != nil {
			formatCUE(state, v, false, false)
			return
		}
		i.Format(state, verb)

	case 'f', 'e', 'E', 'g', 'G':
		d, err := v.Decimal()
		if err != nil {
			formatCUE(state, v, false, false)
			return
		}
		d.Format(state, verb)

	case 's', 'q':
		// TODO: this drops other formatting directives
		msg := "%s"
		if verb == 'q' {
			msg = "%q"
		}

		if b, err := v.Bytes(); err == nil {
			fmt.Fprintf(state, msg, b)
		} else {
			s := fmt.Sprintf("%+v", v)
			fmt.Fprintf(state, msg, s)
		}

	case 'x', 'X':
		switch v.Kind() {
		case StringKind, BytesKind:
			b, _ := v.Bytes()
			// TODO: this drops other formatting directives
			msg := "%x"
			if verb == 'X' {
				msg = "%X"
			}
			fmt.Fprintf(state, msg, b)

		case IntKind, NumberKind:
			var i big.Int
			_, _ = v.Int(&i)
			i.Format(state, verb)

		case FloatKind:
			dec, _ := v.Decimal()
			dec.Format(state, verb)

		default:
			formatCUE(state, v, false, false)
		}

	default:
		formatCUE(state, v, false, false)
	}
}

func formatCUE(state fmt.State, v Value, showDocs, showAll bool) {

	pkgPath := v.instance().ID()

	p := *export.Simplified

	isDef := false
	switch {
	case state.Flag('#'):
		isDef = true
		p = export.Profile{
			ShowOptional:    true,
			ShowDefinitions: true,
			ShowHidden:      true,
		}

	case state.Flag('+'):
		p = *export.Final
		fallthrough

	default:
		p.ShowHidden = showAll
	}

	p.ShowDocs = showDocs
	p.ShowAttributes = showAll

	var n ast.Node
	if isDef {
		n, _ = p.Def(v.idx, pkgPath, v.v)
	} else {
		n, _ = p.Value(v.idx, pkgPath, v.v)
	}

	formatExpr(state, n)
}

func formatExpr(state fmt.State, n ast.Node) {
	opts := make([]format.Option, 0, 3)
	if state.Flag('-') {
		opts = append(opts, format.Simplify())
	}
	// TODO: handle verbs to allow formatting based on type:
	if width, ok := state.Width(); ok {
		opts = append(opts, format.IndentPrefix(width))
	}
	// TODO: consider this: should tabs or spaces be the default?
	if tabwidth, ok := state.Precision(); ok {
		// TODO: 0 means no newlines.
		opts = append(opts,
			format.UseSpaces(tabwidth),
			format.TabIndent(false))
	}
	// TODO: consider this.
	//  else if state.Flag(' ') {
	// 	opts = append(opts,
	// 		format.UseSpaces(4),
	// 		format.TabIndent(false))
	// }

	b, _ := format.Node(n, opts...)
	b = bytes.Trim(b, "\n\r")
	_, _ = state.Write(b)
}
