// Copyright 2016-2019 Alex Stocks
//
// 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 hessian

import (
	"fmt"
	"reflect"
	"strings"
	"sync"
	"unicode"
)

import (
	perrors "github.com/pkg/errors"
)

// invalid consts
const (
	InvalidJavaEnum JavaEnum = -1
)

// struct filed tag of hessian
var tagIdentifier = "hessian"

// SetTagIdentifier for customize struct filed tag of hessian, your can use it like:
//
// hessian.SetTagIdentifier("json")
//
// type MyUser struct {
// 	UserFullName      string   `json:"user_full_name"`
// 	FamilyPhoneNumber string   // default convert to => familyPhoneNumber
// }
//
// var user MyUser
// hessian.NewEncoder().Encode(user)
func SetTagIdentifier(s string) { tagIdentifier = s }

// POJO interface
// !!! Pls attention that Every field name should be upper case.
// Otherwise the app may panic.
type POJO interface {
	JavaClassName() string // got a go struct's Java Class package name which should be a POJO class.
}

// POJOEnum enum for POJO
type POJOEnum interface {
	POJO
	String() string
	EnumValue(string) JavaEnum
}

// JavaEnum type
type JavaEnum int32

// JavaEnumClass struct
type JavaEnumClass struct {
	name string
}

type classInfo struct {
	javaName      string
	fieldNameList []string
	buffer        []byte // encoded buffer
}

type structInfo struct {
	typ      reflect.Type
	goName   string
	javaName string
	index    int // classInfoList index
	inst     interface{}
}

// POJORegistry pojo registry struct
type POJORegistry struct {
	sync.RWMutex
	classInfoList []classInfo           // {class name, field name list...} list
	j2g           map[string]string     // java class name --> go struct name
	registry      map[string]structInfo // go class name --> go struct info
}

var (
	pojoRegistry = POJORegistry{
		j2g:      make(map[string]string),
		registry: make(map[string]structInfo),
	}
	pojoType     = reflect.TypeOf((*POJO)(nil)).Elem()
	javaEnumType = reflect.TypeOf((*POJOEnum)(nil)).Elem()
)

// struct parsing
func showPOJORegistry() {
	pojoRegistry.Lock()
	for k, v := range pojoRegistry.registry {
		fmt.Println("-->> show Registered types <<----")
		fmt.Println(k, v)
	}
	pojoRegistry.Unlock()
}

// RegisterPOJO Register a POJO instance. The return value is -1 if @o has been registered.
func RegisterPOJO(o POJO) int {
	// # definition for an object (compact map)
	// class-def  ::= 'C' string int string*
	pojoRegistry.Lock()
	defer pojoRegistry.Unlock()

	if _, ok := pojoRegistry.registry[o.JavaClassName()]; ok {
		return -1
	}

	var (
		bHeader    []byte
		bBody      []byte
		fieldList  []string
		structInfo structInfo
		clsDef     classInfo
		v          reflect.Value
	)

	v = reflect.ValueOf(o)
	switch v.Kind() {
	case reflect.Struct:
		structInfo.typ = v.Type()
	case reflect.Ptr:
		structInfo.typ = v.Elem().Type()
	default:
		structInfo.typ = reflect.TypeOf(o)
	}

	structInfo.goName = structInfo.typ.String()
	structInfo.javaName = o.JavaClassName()
	structInfo.inst = o
	pojoRegistry.j2g[structInfo.javaName] = structInfo.goName
	registerTypeName(structInfo.goName, structInfo.javaName)

	// prepare fields info of objectDef
	for i := 0; i < structInfo.typ.NumField(); i++ {
		// skip unexported anonymous filed
		if structInfo.typ.Field(i).PkgPath != "" {
			continue
		}

		var fieldName string
		if val, has := structInfo.typ.Field(i).Tag.Lookup(tagIdentifier); has {
			fieldName = val
		} else {
			fieldName = lowerCamelCase(structInfo.typ.Field(i).Name)
		}

		fieldList = append(fieldList, fieldName)
		bBody = encString(bBody, fieldName)
	}

	// prepare header of objectDef
	bHeader = encByte(bHeader, BC_OBJECT_DEF)
	bHeader = encString(bHeader, structInfo.javaName)

	// write fields length into header of objectDef
	// note: cause fieldList is a dynamic slice, so one must calculate length only after it being prepared already.
	bHeader = encInt32(bHeader, int32(len(fieldList)))

	// prepare classDef
	clsDef = classInfo{javaName: structInfo.javaName, fieldNameList: fieldList}

	// merge header and body of objectDef into buffer of classInfo
	clsDef.buffer = append(bHeader, bBody...)

	structInfo.index = len(pojoRegistry.classInfoList)
	pojoRegistry.classInfoList = append(pojoRegistry.classInfoList, clsDef)
	pojoRegistry.registry[structInfo.goName] = structInfo

	return structInfo.index
}

// RegisterPOJOs register a POJO instance arr @os. The return value is @os's
// mathching index array, in which "-1" means its matching POJO has been registered.
func RegisterPOJOs(os ...POJO) []int {
	arr := make([]int, len(os))
	for i := range os {
		arr[i] = RegisterPOJO(os[i])
	}

	return arr
}

// RegisterJavaEnum Register a value type JavaEnum variable.
func RegisterJavaEnum(o POJOEnum) int {
	var (
		ok bool
		b  []byte
		i  int
		n  int
		f  string
		l  []string
		t  structInfo
		c  classInfo
		v  reflect.Value
	)

	pojoRegistry.Lock()
	defer pojoRegistry.Unlock()
	if _, ok = pojoRegistry.registry[o.JavaClassName()]; !ok {
		v = reflect.ValueOf(o)
		switch v.Kind() {
		case reflect.Struct:
			t.typ = v.Type()
		case reflect.Ptr:
			t.typ = v.Elem().Type()
		default:
			t.typ = reflect.TypeOf(o)
		}
		t.goName = t.typ.String()
		t.javaName = o.JavaClassName()
		t.inst = o
		pojoRegistry.j2g[t.javaName] = t.goName

		b = b[:0]
		b = encByte(b, BC_OBJECT_DEF)
		b = encString(b, t.javaName)
		l = l[:0]
		n = 1
		b = encInt32(b, int32(n))
		f = strings.ToLower("name")
		l = append(l, f)
		b = encString(b, f)

		c = classInfo{javaName: t.javaName, fieldNameList: l}
		c.buffer = append(c.buffer, b[:]...)
		t.index = len(pojoRegistry.classInfoList)
		pojoRegistry.classInfoList = append(pojoRegistry.classInfoList, c)
		pojoRegistry.registry[t.goName] = t
		i = t.index
	} else {
		i = -1
	}

	return i
}

// check if go struct name @goName has been registered or not.
func checkPOJORegistry(goName string) (int, bool) {
	var (
		ok bool
		s  structInfo
	)
	pojoRegistry.RLock()
	s, ok = pojoRegistry.registry[goName]
	pojoRegistry.RUnlock()

	return s.index, ok
}

// @typeName is class's java name
func getStructInfo(javaName string) (structInfo, bool) {
	var (
		ok bool
		g  string
		s  structInfo
	)

	pojoRegistry.RLock()
	g, ok = pojoRegistry.j2g[javaName]
	if ok {
		s, ok = pojoRegistry.registry[g]
	}
	pojoRegistry.RUnlock()

	return s, ok
}

func getStructDefByIndex(idx int) (reflect.Type, classInfo, error) {
	var (
		ok      bool
		clsName string
		cls     classInfo
		s       structInfo
	)

	pojoRegistry.RLock()
	defer pojoRegistry.RUnlock()

	if len(pojoRegistry.classInfoList) <= idx || idx < 0 {
		return nil, cls, perrors.Errorf("illegal class index @idx %d", idx)
	}
	cls = pojoRegistry.classInfoList[idx]
	clsName, ok = pojoRegistry.j2g[cls.javaName]
	if !ok {
		return nil, cls, perrors.Errorf("can not find java type name %s in registry", cls.javaName)
	}
	s, ok = pojoRegistry.registry[clsName]
	if !ok {
		return nil, cls, perrors.Errorf("can not find go type name %s in registry", clsName)
	}

	return s.typ, cls, nil
}

// Create a new instance by its struct name is @goName.
// the return value is nil if @o has been registered.
func createInstance(goName string) interface{} {
	var (
		ok bool
		s  structInfo
	)

	pojoRegistry.RLock()
	s, ok = pojoRegistry.registry[goName]
	pojoRegistry.RUnlock()
	if !ok {
		return nil
	}

	return reflect.New(s.typ).Interface()
}

func lowerCamelCase(s string) string {
	runes := []rune(s)
	runes[0] = unicode.ToLower(runes[0])
	return string(runes)
}
