/*
 * 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 (
	"reflect"
)

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

type JavaCollectionObject interface {
	Get() []interface{}
	Set([]interface{})
	JavaClassName() string
}

var collectionTypeMap = make(map[string]reflect.Type, 16)

func SetCollectionSerialize(collection JavaCollectionObject) {
	name := collection.JavaClassName()
	v := reflect.ValueOf(collection)
	var typ reflect.Type
	switch v.Kind() {
	case reflect.Struct:
		typ = v.Type()
	case reflect.Ptr:
		typ = v.Elem().Type()
	default:
		typ = reflect.TypeOf(collection)
	}
	SetSerializer(name, JavaCollectionSerializer{})
	RegisterPOJO(collection)
	collectionTypeMap[name] = typ
}

func getCollectionSerialize(name string) reflect.Type {
	return collectionTypeMap[name]
}

func isCollectionSerialize(name string) bool {
	return getCollectionSerialize(name) != nil
}

type JavaCollectionSerializer struct{}

func (JavaCollectionSerializer) EncObject(e *Encoder, vv POJO) error {
	var err error
	v, ok := vv.(JavaCollectionObject)
	if !ok {
		return perrors.New("can not be converted into java collection object")
	}
	collectionName := v.JavaClassName()
	if collectionName == "" {
		return perrors.New("collection name empty")
	}
	list := v.Get()
	length := len(list)
	typeName := v.JavaClassName()
	err = writeCollectionBegin(length, typeName, e)
	if err != nil {
		return err
	}
	for i := 0; i < length; i++ {
		if err = e.Encode(list[i]); err != nil {
			return err
		}
	}
	return nil
}

func (JavaCollectionSerializer) DecObject(d *Decoder, typ reflect.Type, cls *classInfo) (interface{}, error) {
	// for the java impl of hessian encode collections as list, which will not be decoded as object in go impl, this method should not be called
	return nil, perrors.New("unexpected collection decode call")
}

func (d *Decoder) decodeCollection(length int, listTyp string) (interface{}, error) {
	typ := getCollectionSerialize(listTyp)
	if typ == nil {
		return nil, perrors.New("no collection deserialize set as " + listTyp)
	}
	v := reflect.New(typ).Interface()
	collcetionV, ok := v.(JavaCollectionObject)
	if !ok {
		return nil, perrors.New("collection deserialize err " + listTyp)
	}
	list, err := d.readTypedListValue(length, "", false)
	if err != nil {
		return nil, err
	}
	listInterface, err := EnsureInterface(list, nil)
	if err != nil {
		return nil, err
	}
	listV, listOk := listInterface.([]interface{})
	if !listOk {
		return nil, perrors.New("collection deserialize err " + listTyp)
	}
	collcetionV.Set(listV)
	return collcetionV, nil
}

func writeCollectionBegin(length int, typeName string, e *Encoder) error {
	var err error
	if length <= int(LIST_DIRECT_MAX) {
		e.Append([]byte{BC_LIST_DIRECT + byte(length)})
		err = e.Encode(typeName)
		if err != nil {
			return err
		}
	} else {
		e.Append([]byte{BC_LIST_FIXED})
		err = e.Encode(typeName)
		if err != nil {
			return err
		}
		err = e.Encode(int32(length))
		if err != nil {
			return nil
		}
	}
	return nil
}
