/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 {
	return RegisterPOJOMapping(o.JavaClassName(), o)
}

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

	if goName, ok := pojoRegistry.j2g[javaClassName]; ok {
		return pojoRegistry.registry[goName].index
	}

	// JavaClassName shouldn't equal to goName
	if _, ok := pojoRegistry.registry[javaClassName]; ok {
		return -1
	}

	var (
		bHeader   []byte
		bBody     []byte
		fieldList []string
		sttInfo   structInfo
		clsDef    classInfo
	)

	sttInfo.typ = obtainValueType(o)

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

	// prepare fields info of objectDef
	nextStruct := []reflect.Type{sttInfo.typ}
	for len(nextStruct) > 0 {
		current := nextStruct[0]
		if current.Kind() == reflect.Struct {
			for i := 0; i < current.NumField(); i++ {
				// skip unexported anonymous filed
				if current.Field(i).PkgPath != "" {
					continue
				}

				structField := current.Field(i)

				// skip ignored field
				tagVal, hasTag := structField.Tag.Lookup(tagIdentifier)
				if tagVal == `-` {
					continue
				}

				// flat anonymous field
				if structField.Anonymous && structField.Type.Kind() == reflect.Struct {
					nextStruct = append(nextStruct, structField.Type)
					continue
				}

				var fieldName string
				if hasTag {
					fieldName = tagVal
				} else {
					fieldName = lowerCamelCase(structField.Name)
				}

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

		nextStruct = nextStruct[1:]
	}

	// prepare header of objectDef
	bHeader = encByte(bHeader, BC_OBJECT_DEF)
	bHeader = encString(bHeader, sttInfo.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: sttInfo.javaName, fieldNameList: fieldList}

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

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

	return sttInfo.index
}

// UnRegisterPOJOs unregister POJO instances. It is easy for test.
func UnRegisterPOJOs(os ...POJO) []int {
	arr := make([]int, len(os))
	for i := range os {
		arr[i] = unRegisterPOJO(os[i])
	}

	return arr
}

func unRegisterPOJO(o POJO) int {
	pojoRegistry.Lock()
	defer pojoRegistry.Unlock()

	goName := obtainValueType(o).String()

	if structInfo, ok := pojoRegistry.registry[goName]; ok {
		delete(pojoRegistry.j2g, structInfo.javaName)
		listTypeNameMapper.Delete(structInfo.goName)
		// remove registry cache.
		delete(pojoRegistry.registry, structInfo.goName)
		// don't remove registry classInfoList,
		// indexes of registered pojo may be affected.
		return structInfo.index
	}

	return -1
}

func obtainValueType(o interface{}) reflect.Type {
	v := reflect.ValueOf(o)
	switch v.Kind() {
	case reflect.Struct:
		return v.Type()
	case reflect.Ptr:
		return v.Elem().Type()
	}

	return reflect.TypeOf(o)
}

// 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) {
	s, ok := loadPOJORegistry(goName)
	if !ok {
		return -1, false
	}
	return s.index, true
}

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

	return s, 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
	}

	if s.typ.Kind() == reflect.Map {
		return reflect.MakeMap(s.typ).Interface()
	}

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

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