// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package java

import (
	"fmt"
	"strconv"
	"strings"

	"v.io/v23/vdl"
	"v.io/x/ref/lib/vdl/compile"
)

const javaMaxStringLen = 2 << 16 // 64k

// javaConstVal returns the value string for the provided constant value.
func javaConstVal(v *vdl.Value, env *compile.Env) (ret string) {
	if v == nil {
		return "null"
	}
	if v.IsZero() {
		return javaZeroValue(v.Type(), env)
	}

	ret = javaVal(v, env)
	switch v.Type().Kind() {
	case vdl.Complex64, vdl.Complex128, vdl.Enum, vdl.Union, vdl.Uint16, vdl.Uint32, vdl.Uint64:
		return
	}
	if def := env.FindTypeDef(v.Type()); def != nil && def.File != compile.BuiltInFile { // User-defined type.
		ret = fmt.Sprintf("new %s(%s)", javaType(v.Type(), false, env), ret)
	}
	return
}

// javaVal returns the value string for the provided Value.
func javaVal(v *vdl.Value, env *compile.Env) string {
	const longSuffix = "L"
	const floatSuffix = "f"

	if v.Kind() == vdl.Array || (v.Kind() == vdl.List && v.Type().Elem().Kind() == vdl.Byte && v.Type().Name() == "") {
		ret := fmt.Sprintf("new %s[] {", javaType(v.Type().Elem(), false, env))
		for i := 0; i < v.Len(); i++ {
			if i > 0 {
				ret = ret + ", "
			}
			ret = ret + javaConstVal(v.Index(i), env)
		}
		return ret + "}"
	}

	switch v.Kind() {
	case vdl.Bool:
		if v.Bool() {
			return "true"
		} else {
			return "false"
		}
	case vdl.Byte:
		return "(byte)" + strconv.FormatUint(uint64(v.Byte()), 10)
	case vdl.Uint16:
		return fmt.Sprintf("new %s((short) %s)", javaType(v.Type(), true, env), strconv.FormatUint(v.Uint(), 10))
	case vdl.Int16:
		return "(short)" + strconv.FormatInt(v.Int(), 10)
	case vdl.Uint32:
		return fmt.Sprintf("new %s((int) %s)", javaType(v.Type(), true, env), strconv.FormatUint(v.Uint(), 10)+longSuffix)
	case vdl.Int32:
		return strconv.FormatInt(v.Int(), 10)
	case vdl.Uint64:
		return fmt.Sprintf("new %s(%s)", javaType(v.Type(), true, env), strconv.FormatInt(int64(v.Uint()), 10)+longSuffix)
	case vdl.Int64:
		return strconv.FormatInt(v.Int(), 10) + longSuffix
	case vdl.Float32, vdl.Float64:
		c := strconv.FormatFloat(v.Float(), 'g', -1, bitlen(v.Kind()))
		if strings.Index(c, ".") == -1 {
			c += ".0"
		}
		if v.Kind() == vdl.Float32 {
			return c + floatSuffix
		}
		return c
	case vdl.Complex64, vdl.Complex128:
		r := strconv.FormatFloat(real(v.Complex()), 'g', -1, bitlen(v.Kind()))
		i := strconv.FormatFloat(imag(v.Complex()), 'g', -1, bitlen(v.Kind()))
		if v.Kind() == vdl.Complex64 {
			r = r + "f"
			i = i + "f"
		}
		return fmt.Sprintf("new %s(%s, %s)", javaType(v.Type(), true, env), r, i)
	case vdl.String:
		in := v.RawString()
		if len(in) < javaMaxStringLen {
			return strconv.Quote(in)
		}

		// Java is unable to handle constant strings larger than 64k so split them into multiple strings.
		out := "String.join(\"\", new java.util.ArrayList<CharSequence>("
		for len(in) > javaMaxStringLen {
			out += strconv.Quote(in[:javaMaxStringLen]) + ","
			in = in[javaMaxStringLen:]
		}
		return out + strconv.Quote(in) + "))"
	case vdl.Any:
		if v.Elem() == nil {
			return fmt.Sprintf("new %s()", javaType(v.Type(), false, env))
		}
		elemReflectTypeStr := javaReflectType(v.Elem().Type(), env)
		elemStr := javaConstVal(v.Elem(), env)
		return fmt.Sprintf("new %s(%s, %s)", javaType(v.Type(), false, env), elemReflectTypeStr, elemStr)
	case vdl.Enum:
		return fmt.Sprintf("%s.%s", javaType(v.Type(), false, env), v.EnumLabel())
	case vdl.List:
		elemTypeStr := javaType(v.Type().Elem(), true, env)
		ret := fmt.Sprintf("new com.google.common.collect.ImmutableList.Builder<%s>()", elemTypeStr)
		for i := 0; i < v.Len(); i++ {
			ret = fmt.Sprintf("%s.add(%s)", ret, javaConstVal(v.Index(i), env))
		}
		return ret + ".build()"
	case vdl.Map:
		keyTypeStr := javaType(v.Type().Key(), true, env)
		elemTypeStr := javaType(v.Type().Elem(), true, env)
		ret := fmt.Sprintf("new com.google.common.collect.ImmutableMap.Builder<%s, %s>()", keyTypeStr, elemTypeStr)
		for _, key := range vdl.SortValuesAsString(v.Keys()) {
			keyStr := javaConstVal(key, env)
			elemStr := javaConstVal(v.MapIndex(key), env)
			ret = fmt.Sprintf("%s.put(%s, %s)", ret, keyStr, elemStr)
		}
		return ret + ".build()"
	case vdl.Union:
		index, value := v.UnionField()
		name := v.Type().Field(index).Name
		elemStr := javaConstVal(value, env)
		return fmt.Sprintf("new %s.%s(%s)", javaType(v.Type(), false, env), name, elemStr)
	case vdl.Set:
		keyTypeStr := javaType(v.Type().Key(), true, env)
		ret := fmt.Sprintf("new com.google.common.collect.ImmutableSet.Builder<%s>()", keyTypeStr)
		for _, key := range vdl.SortValuesAsString(v.Keys()) {
			ret = fmt.Sprintf("%s.add(%s)", ret, javaConstVal(key, env))
		}
		return ret + ".build()"
	case vdl.Struct:
		var ret string
		for i := 0; i < v.Type().NumField(); i++ {
			if i > 0 {
				ret = ret + ", "
			}
			ret = ret + javaConstVal(v.StructField(i), env)
		}
		return ret
	case vdl.TypeObject:
		return fmt.Sprintf("new %s(%s)", javaType(v.Type(), false, env), javaReflectType(v.TypeObject(), env))
	case vdl.Optional:
		if v.Elem() != nil {
			return fmt.Sprintf("io.v.v23.vdl.VdlOptional.of(%s)", javaConstVal(v.Elem(), env))
		} else {
			return fmt.Sprintf("new %s(%s)", javaType(v.Type(), false, env), javaReflectType(v.Type(), env))
		}
	}
	panic(fmt.Errorf("vdl: javaVal unhandled type %v %v", v.Kind(), v.Type()))
}

// javaZeroValue returns the zero value string for the provided VDL value.
// We assume that default constructor of user-defined types returns a zero value.
func javaZeroValue(t *vdl.Type, env *compile.Env) string {
	if _, ok := javaNativeType(t, env); ok {
		return "null"
	}

	// First process user-defined types.
	switch t.Kind() {
	case vdl.Enum:
		return fmt.Sprintf("%s.%s", javaType(t, false, env), t.EnumLabel(0))
	case vdl.Union:
		return fmt.Sprintf("new %s.%s()", javaType(t, false, env), t.Field(0).Name)
	}
	if def := env.FindTypeDef(t); def != nil && def.File != compile.BuiltInFile {
		return fmt.Sprintf("new %s()", javaType(t, false, env))
	}

	// Arrays, enums, structs and unions can be user-defined only.
	if t.Kind() == vdl.List && t.Elem().Kind() == vdl.Byte {
		return fmt.Sprintf("new %s[]{}", javaType(t.Elem(), false, env))
	}
	switch t.Kind() {
	case vdl.Bool:
		return "false"
	case vdl.Byte:
		return "(byte) 0"
	case vdl.Int16:
		return "(short) 0"
	case vdl.Int32:
		return "0"
	case vdl.Int64:
		return "0L"
	case vdl.Float32:
		return "0.0f"
	case vdl.Float64:
		return "0.0"
	case vdl.Any, vdl.Complex64, vdl.Complex128, vdl.TypeObject, vdl.Uint16, vdl.Uint32, vdl.Uint64:
		return fmt.Sprintf("new %s()", javaType(t, false, env))
	case vdl.String:
		return "\"\""
	case vdl.List:
		return fmt.Sprintf("new java.util.ArrayList<%s>()", javaType(t.Elem(), true, env))
	case vdl.Map:
		keyTypeStr := javaType(t.Key(), true, env)
		elemTypeStr := javaType(t.Elem(), true, env)
		return fmt.Sprintf("new java.util.HashMap<%s, %s>()", keyTypeStr, elemTypeStr)
	case vdl.Set:
		return fmt.Sprintf("new java.util.HashSet<%s>()", javaType(t.Key(), true, env))
	case vdl.Optional:
		return fmt.Sprintf("new %s(%s)", javaType(t, false, env), javaReflectType(t, env))
	}
	panic(fmt.Errorf("vdl: javaZeroValue unhandled type %v", t))
}
