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

import (
	"fmt"
	"github.com/go-chassis/go-chassis/pkg/runtime"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"

	mesherCommon "github.com/apache/servicecomb-mesher/proxy/common"
	"github.com/apache/servicecomb-mesher/proxy/protocol/dubbo/client"
	"github.com/apache/servicecomb-mesher/proxy/protocol/dubbo/dubbo"
	"github.com/apache/servicecomb-mesher/proxy/protocol/dubbo/schema"
	"github.com/apache/servicecomb-mesher/proxy/protocol/dubbo/utils"

	"github.com/apache/servicecomb-mesher/proxy/protocol"
	"github.com/go-chassis/go-chassis/core/common"
	chassisconfig "github.com/go-chassis/go-chassis/core/config"
	"github.com/go-chassis/go-chassis/core/handler"
	"github.com/go-chassis/go-chassis/core/invocation"
	"github.com/go-chassis/go-chassis/core/loadbalancer"
	"github.com/go-chassis/go-chassis/pkg/string"
	"github.com/go-chassis/go-chassis/pkg/util/tags"
	"github.com/go-chassis/go-chassis/third_party/forked/afex/hystrix-go/hystrix"
	"github.com/go-mesh/openlogging"
)

//ConvertDubboRspToRestRsp is a function which converts dubbo response to rest response
func ConvertDubboRspToRestRsp(dubboRsp *dubbo.DubboRsp, w http.ResponseWriter, ctx *dubbo.InvokeContext) error {
	status := dubboRsp.GetStatus()
	if status == dubbo.Ok {
		w.WriteHeader(http.StatusOK)
		rspSchema := (*(ctx.Method)).GetRspSchema(http.StatusOK)
		if rspSchema != nil {
			v, err := util.ObjectToString(rspSchema.DType, dubboRsp.GetValue())
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
			} else {
				w.Write([]byte(v))
			}
		} else {
			w.WriteHeader(http.StatusInternalServerError)
		}
	} else {
		w.WriteHeader(http.StatusInternalServerError)
	}
	return nil
}

//ConvertHTTPReqToDubboReq is a function which converts http request in to dubbo request
func ConvertHTTPReqToDubboReq(restReq *http.Request, ctx *dubbo.InvokeContext, inv *invocation.Invocation) error {
	req := ctx.Req
	uri := restReq.URL
	i := 0
	var dubboArgs []util.Argument
	queryAgrs := uri.Query()
	arg := &util.Argument{}

	svcSchema, methd := schema.GetSchemaMethodBySvcURL(inv.MicroServiceName, "", inv.RouteTags.Version(), inv.RouteTags.AppID(),
		strings.ToLower(restReq.Method), string(restReq.URL.String()))
	if methd == nil {
		return &util.BaseError{"Method not been found"}
	}
	req.SetMethodName(methd.OperaID)
	req.SetAttachment(dubbo.DubboVersionKey, dubbo.DubboVersion)
	req.SetAttachment(dubbo.PathKey, svcSchema.Info["x-java-interface"]) //interfaceSchema.JavaClsName
	req.SetAttachment(dubbo.VersionKey, "0.0.0")
	ctx.Method = methd
	var err error

	//处理参数
	dubboArgs = make([]util.Argument, len(methd.Paras))

	for _, v := range methd.Paras {
		var byteTmp []byte
		var bytesTmp [][]byte
		itemType := "string" //默认为string
		if strings.EqualFold(v.Where, "query") {
			byteTmp = []byte(queryAgrs.Get(v.Name))
		} else if restReq.Body != nil {
			byteTmp, _ = ioutil.ReadAll(restReq.Body)
		}
		if byteTmp == nil && v.Required {
			return &util.BaseError{"Param is null"}
		}
		var realJvmType string
		bytesTmp, realJvmType = getJVMType(v, arg, bytesTmp, restReq.URL)
		if bytesTmp == nil {
			arg.Value, err = util.RestByteToValue(arg.JavaType, byteTmp)
			if err != nil {
				return err
			}
		} else {
			arg.Value, err = util.RestBytesToLstValue(itemType, bytesTmp)
			if err != nil {
				return err
			}
		}

		if realJvmType != "" {
			arg.JavaType = realJvmType
		}
		dubboArgs[i] = *arg
		i++
	}

	req.SetArguments(dubboArgs)

	return nil
}

func getJVMType(v schema.MethParam, arg *util.Argument, bytesTmp [][]byte, queryAgrs *url.URL) ([][]byte, string) {
	var realJvmType string
	queryAgrsTmp := queryAgrs.Query()
	if _, ok := util.SchemeTypeMAP[v.Dtype]; ok {
		arg.JavaType = util.SchemeTypeMAP[v.Dtype]
		if v.Dtype == util.SchemaArray {
			realJvmType = util.JavaList
			if v.Items != nil {
				if val, ok := v.Items["x-java-class"]; ok {
					realJvmType = fmt.Sprintf("L%s;", val)
				}
				if valType, ok := v.Items["type"]; ok {
					realJvmType = fmt.Sprintf("L%s;", valType)
				}
			}
			bytesTmp = util.S2ByteSlice(queryAgrsTmp[v.Name])
		} else if arg.JavaType == util.JavaObject {
			realJvmType = fmt.Sprintf("L%s;", v.ObjRef.JvmClsName)
			if v.AdditionalProps != nil { //处理map
				if val, ok := v.AdditionalProps["x-java-class"]; ok {
					realJvmType = fmt.Sprintf("L%s;", val)
				} else {
					realJvmType = util.JavaMap
				}
			}
		}
		//Lcom.alibaba.dubbo.demo.user; need convert to  Lcom/alibaba/dubbo/demo/User;
		realJvmType = strings.Replace(realJvmType, ".", "/", -1)
	}
	return bytesTmp, realJvmType
}

func preHandleToDubbo(req *http.Request) (*invocation.Invocation, string) {
	inv := new(invocation.Invocation)
	inv.MicroServiceName = runtime.ServiceName
	inv.RouteTags = utiltags.NewDefaultTag(runtime.Version, chassisconfig.GlobalDefinition.AppID)

	inv.Protocol = "dubbo"
	inv.URLPathFormat = req.URL.Path
	inv.Reply = &dubboclient.WrapResponse{nil}
	source := stringutil.SplitFirstSep(req.RemoteAddr, ":")
	return inv, source
}

//TransparentForwardHandler is a function
func TransparentForwardHandler(w http.ResponseWriter, r *http.Request) {
	inv, _ := preHandleToDubbo(r)
	dubboCtx := &dubbo.InvokeContext{dubbo.NewDubboRequest(), &dubbo.DubboRsp{}, nil, "", ""}
	err := ConvertHTTPReqToDubboReq(r, dubboCtx, inv)
	if err != nil {
		openlogging.Error("Invalid Request: " + err.Error())
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	inv.Args = dubboCtx.Req

	c, err := handler.GetChain(common.Provider, mesherCommon.ChainProviderIncoming)
	if err != nil {
		openlogging.Error("Get Chain failed: " + err.Error())
		return
	}
	c.Next(inv, func(ir *invocation.Response) error {
		return handleRequestForDubbo(w, inv, ir)
	})
	dubboRsp := inv.Reply.(*dubboclient.WrapResponse).Resp
	if dubboRsp != nil {
		err := ConvertDubboRspToRestRsp(dubboRsp, w, dubboCtx)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			w.Write(stringutil.Str2bytes(err.Error()))
		}
	}
}

func handleRequestForDubbo(w http.ResponseWriter, inv *invocation.Invocation, ir *invocation.Response) error {
	if ir != nil {
		if ir.Err != nil {
			switch ir.Err.(type) {
			case hystrix.FallbackNullError:
				w.WriteHeader(http.StatusOK)
				ir.Status = http.StatusOK
			case hystrix.CircuitError:
				w.WriteHeader(http.StatusServiceUnavailable)
				ir.Status = http.StatusServiceUnavailable
				w.Write([]byte(ir.Err.Error()))
			case loadbalancer.LBError:
				w.WriteHeader(http.StatusBadGateway)
				ir.Status = http.StatusBadGateway
				w.Write([]byte(ir.Err.Error()))
			default:
				w.WriteHeader(http.StatusInternalServerError)
				ir.Status = http.StatusInternalServerError
				w.Write([]byte(ir.Err.Error()))
			}
			return ir.Err
		}
		if inv.Endpoint == "" {
			w.WriteHeader(http.StatusInternalServerError)
			ir.Status = http.StatusInternalServerError
			w.Write([]byte(protocol.ErrUnknown.Error()))
			return protocol.ErrUnknown
		}
	} else {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(protocol.ErrUnExpectedHandlerChainResponse.Error()))
		return protocol.ErrUnExpectedHandlerChainResponse
	}

	return nil
}
