// 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"
	"log"
	"path"
	"strings"

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

func javaFullyQualifiedNamedType(def *compile.TypeDef, forceClass bool, env *compile.Env) string {
	if def.File == compile.BuiltInFile {
		name, _ := javaBuiltInType(def.Type, forceClass)
		return name
	}
	name, _ := javaTypeName(def, env)
	return javaPath(path.Join(javaGenPkgPath(def.File.Package.GenPath), name))
}

// javaReflectType returns java.reflect.Type string for provided VDL type.
func javaReflectType(t *vdl.Type, env *compile.Env) string {
	return fmt.Sprintf("new com.google.common.reflect.TypeToken<%s>(){}.getType()", javaType(t, true, env))
}

// javaBuiltInType returns the type name for the provided built in type
// definition, forcing the use of a java class (e.g., java.lang.Integer) if so
// desired.  This method also returns a boolean value indicating whether the
// returned type is a class.
func javaBuiltInType(typ *vdl.Type, forceClass bool) (string, bool) {
	if typ == nil {
		if forceClass {
			return "java.lang.Void", true
		} else {
			return "void", false
		}
	}
	switch typ.Kind() {
	case vdl.Bool:
		if forceClass {
			return "java.lang.Boolean", true
		} else {
			return "boolean", false
		}
	case vdl.Byte:
		if forceClass {
			return "java.lang.Byte", true
		} else {
			return "byte", false
		}
	case vdl.Uint16:
		return "io.v.v23.vdl.VdlUint16", true
	case vdl.Int16:
		if forceClass {
			return "java.lang.Short", true
		} else {
			return "short", false
		}
	case vdl.Uint32:
		return "io.v.v23.vdl.VdlUint32", true
	case vdl.Int32:
		if forceClass {
			return "java.lang.Integer", true
		} else {
			return "int", false
		}
	case vdl.Uint64:
		return "io.v.v23.vdl.VdlUint64", true
	case vdl.Int64:
		if forceClass {
			return "java.lang.Long", true
		} else {
			return "long", false
		}
	case vdl.Float32:
		if forceClass {
			return "java.lang.Float", true
		} else {
			return "float", false
		}
	case vdl.Float64:
		if forceClass {
			return "java.lang.Double", true
		} else {
			return "double", false
		}
	case vdl.Complex64:
		return "io.v.v23.vdl.VdlComplex64", true
	case vdl.Complex128:
		return "io.v.v23.vdl.VdlComplex128", true
	case vdl.String:
		return "java.lang.String", true
	case vdl.TypeObject:
		return "io.v.v23.vdl.VdlTypeObject", true
	case vdl.Any:
		return "io.v.v23.vdl.VdlAny", true
	default:
		return "", false
	}
}

func javaTypeName(def *compile.TypeDef, env *compile.Env) (string, string) {
	if native, ok := def.File.Package.Config.Java.WireTypeRenames[def.Name]; ok {
		return native, accessModifierForName(native)
	}
	return vdlutil.FirstRuneToUpper(def.Name), accessModifierForName(def.Name)
}

func javaNativeType(t *vdl.Type, env *compile.Env) (string, bool) {
	if t == vdl.ErrorType {
		return "io.v.v23.verror.VException", true
	}
	if def := env.FindTypeDef(t); def != nil {
		pkg := def.File.Package
		name, _ := javaTypeName(def, env)
		if native, ok := pkg.Config.Java.WireToNativeTypes[name]; ok {
			// There is a Java native type configured for this defined type.
			return native, true
		}
	}
	return "", false
}

func javaType(t *vdl.Type, forceClass bool, env *compile.Env) string {
	if t == nil {
		name, _ := javaBuiltInType(nil, forceClass)
		return name
	}
	if native, ok := javaNativeType(t, env); ok {
		return native
	}
	if def := env.FindTypeDef(t); def != nil {
		return javaFullyQualifiedNamedType(def, forceClass, env)
	}
	switch t.Kind() {
	case vdl.Array:
		return fmt.Sprintf("%s[]", javaType(t.Elem(), false, env))
	case vdl.List:
		// NOTE(spetrovic): We represent byte lists as Java byte arrays, as it's doubtful anybody
		// would want to use them as Java lists.
		if javaType(t.Elem(), false, env) == "byte" {
			return fmt.Sprintf("byte[]")
		}
		return fmt.Sprintf("%s<%s>", "java.util.List", javaType(t.Elem(), true, env))
	case vdl.Set:
		return fmt.Sprintf("%s<%s>", "java.util.Set", javaType(t.Key(), true, env))
	case vdl.Map:
		return fmt.Sprintf("%s<%s, %s>", "java.util.Map", javaType(t.Key(), true, env), javaType(t.Elem(), true, env))
	case vdl.Optional:
		return fmt.Sprintf("io.v.v23.vdl.VdlOptional<%s>", javaType(t.Elem(), true, env))
	default:
		log.Fatalf("vdl: javaType unhandled type %v %v", t.Kind(), t)
		return ""
	}
}

func javaVdlPrimitiveType(kind vdl.Kind) string {
	switch kind {
	case vdl.Bool, vdl.Byte, vdl.Uint16, vdl.Uint32, vdl.Uint64, vdl.Int16, vdl.Int32, vdl.Int64, vdl.Float32, vdl.Float64, vdl.Complex128, vdl.Complex64, vdl.String:
		return "io.v.v23.vdl.Vdl" + vdlutil.FirstRuneToUpper(kind.String())
	}
	log.Fatalf("val: unhandled kind: %v", kind)
	return ""
}

// javaHashCode returns the java code for the hashCode() computation for a given type.
func javaHashCode(name string, ty *vdl.Type, env *compile.Env) string {
	if isJavaNativeArray(ty, env) {
		return fmt.Sprintf("java.util.Arrays.hashCode(%s)", name)
	}
	if def := env.FindTypeDef(ty); def != nil && def.File == compile.BuiltInFile {
		switch ty.Kind() {
		case vdl.Bool:
			return fmt.Sprintf("java.lang.Boolean.valueOf(%s).hashCode()", name)
		case vdl.Byte, vdl.Int16:
			return "(int)" + name
		case vdl.Int32:
			return name
		case vdl.Int64:
			return fmt.Sprintf("java.lang.Long.valueOf(%s).hashCode()", name)
		case vdl.Float32:
			return fmt.Sprintf("java.lang.Float.valueOf(%s).hashCode()", name)
		case vdl.Float64:
			return fmt.Sprintf("java.lang.Double.valueOf(%s).hashCode()", name)
		}
	}
	return fmt.Sprintf("(%s == null ? 0 : %s.hashCode())", name, name)
}

// isClass returns true iff the provided type is represented by a Java class.
func isClass(t *vdl.Type, env *compile.Env) bool {
	if t == nil { // void type
		return false
	}
	if def := env.FindTypeDef(t); def != nil && def.File == compile.BuiltInFile {
		// Built-in type.  See if it's represented by a class.
		if tname, isClass := javaBuiltInType(t, false); tname != "" && !isClass {
			return false
		}
	}
	return true
}

// isJavaNativeArray returns true iff the provided type is represented by a Java array.
func isJavaNativeArray(t *vdl.Type, env *compile.Env) bool {
	typeStr := javaType(t, false, env)
	return strings.HasSuffix(typeStr, "[]")
}

func bitlen(kind vdl.Kind) int {
	switch kind {
	case vdl.Float32, vdl.Complex64:
		return 32
	case vdl.Float64, vdl.Complex128:
		return 64
	}
	panic(fmt.Errorf("vdl: bitLen unhandled kind %v", kind))
}
