package rpc

import (
	"errors"
	"fmt"
	"reflect"
)

var stringType = reflect.TypeOf("")

type ValueParserBuilder struct {
}

func (builder *ValueParserBuilder) parseJsonBoolean(jsonValue interface{}, valueName string) (interface{}, error) {
	if jsonValue == nil {
		return nil, errors.New(fmt.Sprintf("%s 不能为空!", valueName))
	} else if value, ok := jsonValue.(bool); !ok {
		return nil, errors.New(fmt.Sprintf("%s 无法解析!源类型:%v,目标类型:Bool.", valueName, reflect.TypeOf(jsonValue)))
	} else {
		return value, nil
	}
}

func (builder *ValueParserBuilder) parseJsonString(jsonValue interface{}, valueName string) (interface{}, error) {
	if jsonValue == nil {
		return "", nil
	} else if value, ok := jsonValue.(string); !ok {
		return nil, errors.New(fmt.Sprintf("%s 无法解析!源类型:%v,目标类型:String.", valueName, reflect.TypeOf(jsonValue)))
	} else {
		return value, nil
	}
}

func (builder *ValueParserBuilder) parseJsonNumber(jsonValue interface{}, valueName string) (float64, error) {
	if jsonValue == nil {
		return 0, errors.New(fmt.Sprintf("%s 不能为空!", valueName))
	} else if value, ok := jsonValue.(float64); !ok {
		return 0, errors.New(fmt.Sprintf("%s 无法解析!源类型:%v,目标类型:Number.", valueName, reflect.TypeOf(jsonValue)))
	} else {
		return value, nil
	}
}

func (builder *ValueParserBuilder) parseJsonArray(jsonValue interface{}, valueName string) ([]interface{}, error) {
	if jsonValue == nil {
		return nil, errors.New(fmt.Sprintf("%s 不能为空!", valueName))
	} else if items, ok := jsonValue.([]interface{}); !ok {
		return nil, errors.New(fmt.Sprintf("%s 无法解析!源类型:%v,目标类型:Array.", valueName, reflect.TypeOf(jsonValue)))
	} else {
		return items, nil
	}
}

func (builder *ValueParserBuilder) parseJsonObject(jsonValue interface{}, valueName string) (map[string]interface{}, error) {
	if jsonValue == nil {
		return nil, errors.New(fmt.Sprintf("%s 不能为空!", valueName))
	} else if jsonObject, ok := jsonValue.(map[string]interface{}); !ok {
		return nil, errors.New(fmt.Sprintf("%s 无法解析!源类型:%v,目标类型:Object.", valueName, reflect.TypeOf(jsonValue)))
	} else {
		return jsonObject, nil
	}
}

func (builder *ValueParserBuilder) parseUnsignedInteger(jsonValue interface{}, valueName string) (interface{}, error) {
	if value, err := builder.parseJsonNumber(jsonValue, valueName); err != nil {
		return nil, err
	} else {
		return uint(value), nil
	}
}

func (builder *ValueParserBuilder) parseUnsignedInteger8(jsonValue interface{}, valueName string) (interface{}, error) {
	if value, err := builder.parseJsonNumber(jsonValue, valueName); err != nil {
		return nil, err
	} else {
		return uint8(value), nil
	}
}

func (builder *ValueParserBuilder) parseUnsignedInteger16(jsonValue interface{}, valueName string) (interface{}, error) {
	if value, err := builder.parseJsonNumber(jsonValue, valueName); err != nil {
		return nil, err
	} else {
		return uint16(value), nil
	}
}

func (builder *ValueParserBuilder) parseUnsignedInteger32(jsonValue interface{}, valueName string) (interface{}, error) {
	if value, err := builder.parseJsonNumber(jsonValue, valueName); err != nil {
		return nil, err
	} else {
		return uint32(value), nil
	}
}

func (builder *ValueParserBuilder) parseUnsignedInteger64(jsonValue interface{}, valueName string) (interface{}, error) {
	if value, err := builder.parseJsonNumber(jsonValue, valueName); err != nil {
		return nil, err
	} else {
		return uint64(value), nil
	}
}

func (builder *ValueParserBuilder) parseInteger(jsonValue interface{}, valueName string) (interface{}, error) {
	if value, err := builder.parseJsonNumber(jsonValue, valueName); err != nil {
		return nil, err
	} else {
		return int(value), nil
	}
}

func (builder *ValueParserBuilder) parseInteger8(jsonValue interface{}, valueName string) (interface{}, error) {
	if value, err := builder.parseJsonNumber(jsonValue, valueName); err != nil {
		return nil, err
	} else {
		return int8(value), nil
	}
}

func (builder *ValueParserBuilder) parseInteger16(jsonValue interface{}, valueName string) (interface{}, error) {
	if value, err := builder.parseJsonNumber(jsonValue, valueName); err != nil {
		return nil, err
	} else {
		return int16(value), nil
	}
}

func (builder *ValueParserBuilder) parseInteger32(jsonValue interface{}, valueName string) (interface{}, error) {
	if value, err := builder.parseJsonNumber(jsonValue, valueName); err != nil {
		return nil, err
	} else {
		return int32(value), nil
	}
}

func (builder *ValueParserBuilder) parseInteger64(jsonValue interface{}, valueName string) (interface{}, error) {
	if value, err := builder.parseJsonNumber(jsonValue, valueName); err != nil {
		return nil, err
	} else {
		return int64(value), nil
	}
}

func (builder *ValueParserBuilder) parseFloat32(jsonValue interface{}, valueName string) (interface{}, error) {
	if value, err := builder.parseJsonNumber(jsonValue, valueName); err != nil {
		return nil, err
	} else {
		return float32(value), nil
	}
}

func (builder *ValueParserBuilder) parseFloat64(jsonValue interface{}, valueName string) (interface{}, error) {
	if value, err := builder.parseJsonNumber(jsonValue, valueName); err != nil {
		return nil, err
	} else {
		return value, nil
	}
}

func (builder *ValueParserBuilder) buildMapParser(valueParser valueParser, valueType reflect.Type) valueParser {

	return func(jsonValue interface{}, valueName string) (interface{}, error) {

		if jsonObject, err := builder.parseJsonObject(jsonValue, valueName); err != nil {
			return reflect.Zero(reflect.MapOf(stringType, valueType)).Interface(), nil
		} else {
			result := reflect.MakeMapWithSize(reflect.MapOf(stringType, valueType), len(jsonObject))
			for key, value := range jsonObject {
				if value, err := valueParser(value, fmt.Sprintf("%s[%s]", valueName, key)); err != nil {
					return nil, err
				} else {
					result.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(value))
				}
			}
			return result.Interface(), nil
		}
	}
}

func (builder *ValueParserBuilder) buildSliceParser(itemParser valueParser, elementType reflect.Type) valueParser {

	return func(jsonValue interface{}, valueName string) (interface{}, error) {

		if jsonArray, err := builder.parseJsonArray(jsonValue, valueName); err != nil {
			return reflect.Zero(reflect.SliceOf(elementType)).Interface(), nil
		} else {
			slice := reflect.MakeSlice(reflect.SliceOf(elementType), len(jsonArray), len(jsonArray))
			for index, item := range jsonArray {
				if value, err := itemParser(item, fmt.Sprintf("%s[%d]", valueName, index)); err != nil {
					return nil, err
				} else {
					slice.Index(index).Set(reflect.ValueOf(value))
				}
			}
			return slice.Interface(), nil
		}
	}
}

func (builder *ValueParserBuilder) buildArrayParser(itemParser valueParser, length int, elementType reflect.Type) valueParser {

	return func(jsonValue interface{}, valueName string) (interface{}, error) {

		if jsonArray, err := builder.parseJsonArray(jsonValue, valueName); err != nil {
			return nil, err
		} else if len(jsonArray) != length {
			return nil, errors.New(fmt.Sprintf("%s 数组长度匹配!期望长度:%d,实际长度:%d.", valueName, length, len(jsonArray)))
		} else {
			array := reflect.New(reflect.ArrayOf(length, elementType)).Elem()
			for index := 0; index < length; index++ {
				if value, err := itemParser(jsonArray[index], fmt.Sprintf("%s[%d]", valueName, index)); err != nil {
					return nil, err
				} else {
					array.Index(index).Set(reflect.ValueOf(value))
				}
			}
			return array.Interface(), nil
		}
	}
}

func (builder *ValueParserBuilder) buildPointerParser(itemParser valueParser, elementType reflect.Type) valueParser {

	return func(jsonValue interface{}, valueName string) (interface{}, error) {

		if jsonValue == nil {
			return reflect.Zero(reflect.PtrTo(elementType)).Interface(), nil
		} else if value, err := itemParser(jsonValue, valueName); err != nil {
			return nil, err
		} else {
			pointer := reflect.New(elementType)
			pointer.Elem().Set(reflect.ValueOf(value))
			return pointer.Interface(), nil
		}
	}
}

func (builder *ValueParserBuilder) buildStructParser(valueID string, structType reflect.Type) (valueParser, error) {

	fieldCount := structType.NumField()
	parsers := make(map[string]valueParser, fieldCount)
	for i := 0; i < fieldCount; i++ {
		field := structType.Field(i)
		if parameterParser, err := builder.Build(fmt.Sprintf("%s.%s", valueID, field.Name), field.Type); err != nil {
			return nil, err
		} else {
			parsers[field.Name] = parameterParser
		}
	}

	return func(jsonValue interface{}, valueName string) (interface{}, error) {

		structValue := reflect.New(structType).Elem()
		for fieldName, parser := range parsers {
			field := structValue.FieldByName(fieldName)
			if !field.IsValid() {
				return nil, errors.New(fmt.Sprintf("%s 没有找到字段:%v.%s", valueName, structType, fieldName))
			}
			if jsonObject, err := builder.parseJsonObject(jsonValue, valueName); err != nil {
				return nil, err
			} else if value, err := parser(jsonObject[fieldName], fmt.Sprintf("%s.%s", valueName, fieldName)); err != nil {
				return nil, err
			} else {
				field.Set(reflect.ValueOf(value))
			}
		}
		return structValue.Interface(), nil
	}, nil
}

func (builder *ValueParserBuilder) Build(valueID string, valueType reflect.Type) (valueParser, error) {
	switch valueType.Kind() {
	//case reflect.Invalid:
	case reflect.Bool:
		return builder.parseJsonBoolean, nil
	case reflect.Int:
		return builder.parseInteger, nil
	case reflect.Int8:
		return builder.parseInteger8, nil
	case reflect.Int16:
		return builder.parseInteger16, nil
	case reflect.Int32:
		return builder.parseInteger32, nil
	case reflect.Int64:
		return builder.parseInteger64, nil
	case reflect.Uint:
		return builder.parseUnsignedInteger, nil
	case reflect.Uint8:
		return builder.parseUnsignedInteger8, nil
	case reflect.Uint16:
		return builder.parseUnsignedInteger16, nil
	case reflect.Uint32:
		return builder.parseUnsignedInteger32, nil
	case reflect.Uint64:
		return builder.parseUnsignedInteger64, nil
	//case reflect.Uintptr:
	case reflect.Float32:
		return builder.parseFloat32, nil
	case reflect.Float64:
		return builder.parseFloat64, nil
	//case reflect.Complex64:
	//case reflect.Complex128:
	case reflect.Array:
		parser, err := builder.Build(valueID, valueType.Elem())
		if err != nil {
			return nil, err
		} else {
			return builder.buildArrayParser(parser, valueType.Len(), valueType.Elem()), nil
		}
	//case reflect.Chan:
	//case reflect.Func:
	//case reflect.Interface:
	case reflect.Map:
		if valueType.Key().Kind() != reflect.String {
			return nil, errors.New(fmt.Sprintf("*map[%s]%s", valueType.Key().Name(), valueType.Elem().Name()))
		}
		valuerParser, err := builder.Build(valueID, valueType.Elem())
		if err != nil {
			return nil, err
		} else {
			return builder.buildMapParser(valuerParser, valueType.Elem()), nil
		}
	case reflect.Ptr:
		parser, err := builder.Build(valueID, valueType.Elem())
		if err != nil {
			return nil, err
		} else {
			return builder.buildPointerParser(parser, valueType.Elem()), nil
		}
	case reflect.Slice:
		parser, err := builder.Build(valueID, valueType.Elem())
		if err != nil {
			return nil, err
		} else {
			return builder.buildSliceParser(parser, valueType.Elem()), nil
		}
	case reflect.String:
		return builder.parseJsonString, nil
	case reflect.Struct:
		parser, err := builder.buildStructParser(valueID, valueType)
		if err != nil {
			return nil, err
		} else {
			return parser, nil
		}
	//case reflect.UnsafePointer:
	default:
		return nil, errors.New(fmt.Sprintf("不支持的类型: %s.%s", valueID, valueType.Name()))
	}
}
