package rpc

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

type MethodInvoker struct {
	call             func([]reflect.Value) []reflect.Value
	parameterParsers []valueParser
}

func NewMethodInvoker(call func([]reflect.Value) []reflect.Value, parameterParsers []valueParser) *MethodInvoker {
	return &MethodInvoker{call, parameterParsers}
}

func (invoker *MethodInvoker) parseParameters(jsonArray []interface{}) ([]reflect.Value, error) {

	parsers := invoker.parameterParsers
	count := len(parsers)
	if len(jsonArray) != count {
		return nil, errors.New(fmt.Sprintf("参数长度错误!"))
	} else {
		parameterValues := make([]reflect.Value, count)
		for i, parser := range parsers {
			if parameter, err := parser(jsonArray[i], fmt.Sprintf("#%d", i+1)); err != nil {
				return nil, err
			} else {
				parameterValues[i] = reflect.ValueOf(parameter)
			}
		}
		return parameterValues, nil
	}
}

func (invoker *MethodInvoker) Process(jsonArray []interface{}) (interface{}, error) {

	if parameterValues, err := invoker.parseParameters(jsonArray); err != nil {
		return nil, err
	} else {
		returnValues := invoker.call(parameterValues)
		var err interface{}
		var result interface{}
		if len(returnValues) > 1 {
			err = returnValues[1].Interface()
			result = returnValues[0].Interface()
		} else {
			err = returnValues[0].Interface()
			result = nil
		}
		if err != nil {
			return nil, err.(error)
		} else {
			return result, nil
		}
	}
}
