/*
 * 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 server

import (
	"context"
	"errors"
	"net/http"
	"reflect"
	"strconv"
	"strings"
)

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

import (
	"github.com/apache/dubbo-go/common"
	"github.com/apache/dubbo-go/common/logger"
	"github.com/apache/dubbo-go/protocol"
	"github.com/apache/dubbo-go/protocol/invocation"
	rest_config "github.com/apache/dubbo-go/protocol/rest/config"
)

const parseParameterErrorStr = "An error occurred while parsing parameters on the server"

// RestServer user can implement this server interface
type RestServer interface {
	// Start rest server
	Start(url common.URL)
	// Deploy a http api
	Deploy(restMethodConfig *rest_config.RestMethodConfig, routeFunc func(request RestServerRequest, response RestServerResponse))
	// UnDeploy a http api
	UnDeploy(restMethodConfig *rest_config.RestMethodConfig)
	// Destroy rest server
	Destroy()
}

// RestServerRequest interface
type RestServerRequest interface {
	// RawRequest get the Ptr of http.Request
	RawRequest() *http.Request
	// PathParameter get the path parameter by name
	PathParameter(name string) string
	// PathParameters get the map of the path parameters
	PathParameters() map[string]string
	// QueryParameter get the query parameter by name
	QueryParameter(name string) string
	// QueryParameters get the map of query parameters
	QueryParameters(name string) []string
	// BodyParameter get the body parameter of name
	BodyParameter(name string) (string, error)
	// HeaderParameter get the header parameter of name
	HeaderParameter(name string) string
	// ReadEntity checks the Accept header and reads the content into the entityPointer.
	ReadEntity(entityPointer interface{}) error
}

// RestServerResponse interface
type RestServerResponse interface {
	http.ResponseWriter
	// WriteError writes the http status and the error string on the response. err can be nil.
	// Return an error if writing was not successful.
	WriteError(httpStatus int, err error) (writeErr error)
	// WriteEntity marshals the value using the representation denoted by the Accept Header.
	WriteEntity(value interface{}) error
}

// GetRouteFunc
// A route function will be invoked by http server
func GetRouteFunc(invoker protocol.Invoker, methodConfig *rest_config.RestMethodConfig) func(req RestServerRequest, resp RestServerResponse) {
	return func(req RestServerRequest, resp RestServerResponse) {
		var (
			err  error
			args []interface{}
		)
		svc := common.ServiceMap.GetService(invoker.GetUrl().Protocol, strings.TrimPrefix(invoker.GetUrl().Path, "/"))
		// get method
		method := svc.Method()[methodConfig.MethodName]
		argsTypes := method.ArgsType()
		replyType := method.ReplyType()
		// two ways to prepare arguments
		// if method like this 'func1(req []interface{}, rsp *User) error'
		// we don't have arguments type
		if (len(argsTypes) == 1 || len(argsTypes) == 2 && replyType == nil) &&
			argsTypes[0].String() == "[]interface {}" {
			args, err = getArgsInterfaceFromRequest(req, methodConfig)
		} else {
			args, err = getArgsFromRequest(req, argsTypes, methodConfig)
		}
		if err != nil {
			logger.Errorf("[Go Restful] parsing http parameters error:%v", err)
			err = resp.WriteError(http.StatusInternalServerError, errors.New(parseParameterErrorStr))
			if err != nil {
				logger.Errorf("[Go Restful] WriteErrorString error:%v", err)
			}
		}
		result := invoker.Invoke(context.Background(), invocation.NewRPCInvocation(methodConfig.MethodName, args, make(map[string]string)))
		if result.Error() != nil {
			err = resp.WriteError(http.StatusInternalServerError, result.Error())
			if err != nil {
				logger.Errorf("[Go Restful] WriteError error:%v", err)
			}
			return
		}
		err = resp.WriteEntity(result.Result())
		if err != nil {
			logger.Errorf("[Go Restful] WriteEntity error:%v", err)
		}
	}
}

// getArgsInterfaceFromRequest when service function like GetUser(req []interface{}, rsp *User) error
// use this method to get arguments
func getArgsInterfaceFromRequest(req RestServerRequest, methodConfig *rest_config.RestMethodConfig) ([]interface{}, error) {
	argsMap := make(map[int]interface{}, 8)
	maxKey := 0
	for k, v := range methodConfig.PathParamsMap {
		if maxKey < k {
			maxKey = k
		}
		argsMap[k] = req.PathParameter(v)
	}
	for k, v := range methodConfig.QueryParamsMap {
		if maxKey < k {
			maxKey = k
		}
		params := req.QueryParameters(v)
		if len(params) == 1 {
			argsMap[k] = params[0]
		} else {
			argsMap[k] = params
		}
	}
	for k, v := range methodConfig.HeadersMap {
		if maxKey < k {
			maxKey = k
		}
		argsMap[k] = req.HeaderParameter(v)
	}
	if methodConfig.Body >= 0 {
		if maxKey < methodConfig.Body {
			maxKey = methodConfig.Body
		}
		m := make(map[string]interface{})
		// TODO read as a slice
		if err := req.ReadEntity(&m); err != nil {
			return nil, perrors.Errorf("[Go restful] Read body entity as map[string]interface{} error:%v", err)
		}
		argsMap[methodConfig.Body] = m
	}
	args := make([]interface{}, maxKey+1)
	for k, v := range argsMap {
		if k >= 0 {
			args[k] = v
		}
	}
	return args, nil
}

// getArgsFromRequest get arguments from server.RestServerRequest
func getArgsFromRequest(req RestServerRequest, argsTypes []reflect.Type, methodConfig *rest_config.RestMethodConfig) ([]interface{}, error) {
	argsLength := len(argsTypes)
	args := make([]interface{}, argsLength)
	for i, t := range argsTypes {
		args[i] = reflect.Zero(t).Interface()
	}
	if err := assembleArgsFromPathParams(methodConfig, argsLength, argsTypes, req, args); err != nil {
		return nil, err
	}
	if err := assembleArgsFromQueryParams(methodConfig, argsLength, argsTypes, req, args); err != nil {
		return nil, err
	}
	if err := assembleArgsFromBody(methodConfig, argsTypes, req, args); err != nil {
		return nil, err
	}
	if err := assembleArgsFromHeaders(methodConfig, req, argsLength, argsTypes, args); err != nil {
		return nil, err
	}
	return args, nil
}

// assembleArgsFromHeaders assemble arguments from headers
func assembleArgsFromHeaders(methodConfig *rest_config.RestMethodConfig, req RestServerRequest, argsLength int, argsTypes []reflect.Type, args []interface{}) error {
	for k, v := range methodConfig.HeadersMap {
		param := req.HeaderParameter(v)
		if k < 0 || k >= argsLength {
			return perrors.Errorf("[Go restful] Header param parse error, the index %v args of method:%v doesn't exist", k, methodConfig.MethodName)
		}
		t := argsTypes[k]
		if t.Kind() == reflect.Ptr {
			t = t.Elem()
		}
		if t.Kind() == reflect.String {
			args[k] = param
		} else {
			return perrors.Errorf("[Go restful] Header param parse error, the index %v args's type isn't string", k)
		}
	}
	return nil
}

// assembleArgsFromBody assemble arguments from body
func assembleArgsFromBody(methodConfig *rest_config.RestMethodConfig, argsTypes []reflect.Type, req RestServerRequest, args []interface{}) error {
	if methodConfig.Body >= 0 && methodConfig.Body < len(argsTypes) {
		t := argsTypes[methodConfig.Body]
		kind := t.Kind()
		if kind == reflect.Ptr {
			t = t.Elem()
		}
		var ni interface{}
		if t.String() == "[]interface {}" {
			ni = make([]map[string]interface{}, 0)
		} else if t.String() == "interface {}" {
			ni = make(map[string]interface{})
		} else {
			n := reflect.New(t)
			if n.CanInterface() {
				ni = n.Interface()
			}
		}
		if err := req.ReadEntity(&ni); err != nil {
			return perrors.Errorf("[Go restful] Read body entity error, error is %v", perrors.WithStack(err))
		}
		args[methodConfig.Body] = ni
	}
	return nil
}

// assembleArgsFromQueryParams assemble arguments from query params
func assembleArgsFromQueryParams(methodConfig *rest_config.RestMethodConfig, argsLength int, argsTypes []reflect.Type, req RestServerRequest, args []interface{}) error {
	var (
		err   error
		param interface{}
		i64   int64
	)
	for k, v := range methodConfig.QueryParamsMap {
		if k < 0 || k >= argsLength {
			return perrors.Errorf("[Go restful] Query param parse error, the index %v args of method:%v doesn't exist", k, methodConfig.MethodName)
		}
		t := argsTypes[k]
		kind := t.Kind()
		if kind == reflect.Ptr {
			t = t.Elem()
		}
		if kind == reflect.Slice {
			param = req.QueryParameters(v)
		} else if kind == reflect.String {
			param = req.QueryParameter(v)
		} else if kind == reflect.Int {
			param, err = strconv.Atoi(req.QueryParameter(v))
		} else if kind == reflect.Int32 {
			i64, err = strconv.ParseInt(req.QueryParameter(v), 10, 32)
			if err == nil {
				param = int32(i64)
			}
		} else if kind == reflect.Int64 {
			param, err = strconv.ParseInt(req.QueryParameter(v), 10, 64)
		} else {
			return perrors.Errorf("[Go restful] Query param parse error, the index %v args's type isn't int or string or slice", k)
		}
		if err != nil {
			return perrors.Errorf("[Go restful] Query param parse error, error:%v", perrors.WithStack(err))
		}
		args[k] = param
	}
	return nil
}

// assembleArgsFromPathParams assemble arguments from path params
func assembleArgsFromPathParams(methodConfig *rest_config.RestMethodConfig, argsLength int, argsTypes []reflect.Type, req RestServerRequest, args []interface{}) error {
	var (
		err   error
		param interface{}
		i64   int64
	)
	for k, v := range methodConfig.PathParamsMap {
		if k < 0 || k >= argsLength {
			return perrors.Errorf("[Go restful] Path param parse error, the index %v args of method:%v doesn't exist", k, methodConfig.MethodName)
		}
		t := argsTypes[k]
		kind := t.Kind()
		if kind == reflect.Ptr {
			t = t.Elem()
		}
		if kind == reflect.Int {
			param, err = strconv.Atoi(req.PathParameter(v))
		} else if kind == reflect.Int32 {
			i64, err = strconv.ParseInt(req.PathParameter(v), 10, 32)
			if err == nil {
				param = int32(i64)
			}
		} else if kind == reflect.Int64 {
			param, err = strconv.ParseInt(req.PathParameter(v), 10, 64)
		} else if kind == reflect.String {
			param = req.PathParameter(v)
		} else {
			return perrors.Errorf("[Go restful] Path param parse error, the index %v args's type isn't int or string", k)
		}
		if err != nil {
			return perrors.Errorf("[Go restful] Path param parse error, error is %v", perrors.WithStack(err))
		}
		args[k] = param
	}
	return nil
}
