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

import (
	"context"
)

import (
	hessian "github.com/apache/dubbo-go-hessian2"
	perrors "github.com/pkg/errors"
)

import (
	"dubbo.apache.org/dubbo-go/v3/common"
	"dubbo.apache.org/dubbo-go/v3/common/constant"
	"dubbo.apache.org/dubbo-go/v3/common/extension"
	"dubbo.apache.org/dubbo-go/v3/common/logger"
	"dubbo.apache.org/dubbo-go/v3/filter"
	"dubbo.apache.org/dubbo-go/v3/protocol"
	invocation2 "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
)

func init() {
	extension.SetFilter(constant.GenericServiceFilterKey, func() filter.Filter {
		return &ServiceFilter{}
	})
}

// ServiceFilter is for Server
type ServiceFilter struct{}

func (f *ServiceFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
	if !isGenericInvocation(invocation) {
		return invoker.Invoke(ctx, invocation)
	}

	// get real invocation info from the generic invocation
	mtdname := invocation.Arguments()[0].(string)
	// types are not required in dubbo-go, for dubbo-go client to dubbo-go server, types could be nil
	types := invocation.Arguments()[1]
	args := invocation.Arguments()[2].([]hessian.Object)

	logger.Debugf(`received a generic invocation: 
		MethodName: %s,
		Types: %s,
		Args: %s
	`, mtdname, types, args)

	// get the type of the argument
	ivkUrl := invoker.GetURL()
	svc := common.ServiceMap.GetServiceByServiceKey(ivkUrl.Protocol, ivkUrl.ServiceKey())
	method := svc.Method()[mtdname]
	if method == nil {
		return &protocol.RPCResult{
			Err: perrors.Errorf("\"%s\" method is not found, service key: %s", mtdname, ivkUrl.ServiceKey()),
		}
	}
	argsType := method.ArgsType()

	// get generic info from attachments of invocation, the default value is "true"
	generic := invocation.AttachmentsByKey(constant.GENERIC_KEY, constant.GenericSerializationDefault)
	// get generalizer according to value in the `generic`
	g := getGeneralizer(generic)

	//if strings.ToLower(generic) == constant.GenericSerializationProtobuf {
	//	if len(args) > 1 {
	//		logger.Warnf("\"%s\" only supports one argument, but we get %d arguments actually",
	//			constant.GenericSerializationProtobuf, len(args))
	//	}
	//}

	if len(args) != len(argsType) {
		return &protocol.RPCResult{
			Err: perrors.Errorf("the number of args(=%d) is not matched with \"%s\" method", len(args), mtdname),
		}
	}

	// realize
	newargs := make([]interface{}, len(argsType))
	for i := 0; i < len(argsType); i++ {
		newarg, err := g.Realize(args[i], argsType[i])
		if err != nil {
			return &protocol.RPCResult{
				Err: perrors.Errorf("realization failed, %v", err),
			}
		}
		newargs[i] = newarg
	}

	// build a normal invocation
	newivc := invocation2.NewRPCInvocation(mtdname, newargs, invocation.Attachments())
	newivc.SetReply(invocation.Reply())

	return invoker.Invoke(ctx, newivc)
}

func (f *ServiceFilter) OnResponse(_ context.Context, result protocol.Result, _ protocol.Invoker, invocation protocol.Invocation) protocol.Result {
	if isGenericInvocation(invocation) && result.Result() != nil {
		// get generic info from attachments of invocation, the default value is "true"
		generic := invocation.AttachmentsByKey(constant.GENERIC_KEY, constant.GenericSerializationDefault)
		// get generalizer according to value in the `generic`
		g := getGeneralizer(generic)

		obj, err := g.Generalize(result.Result())
		if err != nil {
			err = perrors.Errorf("generalizaion failed, %v", err)
			result.SetError(err)
			result.SetResult(nil)
			return result
		}
		result.SetResult(obj)
	}
	return result
}
