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

import (
	"context"
	"strconv"
	"sync"
	"sync/atomic"
)

import (
	"github.com/modern-go/concurrent"
)

import (
	"github.com/apache/dubbo-go/common/constant"
	"github.com/apache/dubbo-go/common/extension"
	"github.com/apache/dubbo-go/common/logger"
	"github.com/apache/dubbo-go/filter"
	_ "github.com/apache/dubbo-go/filter/handler"
	"github.com/apache/dubbo-go/protocol"
)

const (
	name = "execute"
)

func init() {
	extension.SetFilter(name, GetExecuteLimitFilter)
}

/**
 * ExecuteLimitFilter
 * The filter will limit the number of in-progress request and it's thread-safe.
 * example:
 * "UserProvider":
 *   registry: "hangzhouzk"
 *   protocol : "dubbo"
 *   interface : "com.ikurento.user.UserProvider"
 *   ... # other configuration
 *   execute.limit: 200 # the name of MethodServiceTpsLimiterImpl. if the value < 0, invocation will be ignored.
 *   execute.limit.rejected.handle: "default" # the name of rejected handler
 *   methods:
 *    - name: "GetUser"
 *      execute.limit: 20, # in this case, this configuration in service-level will be ignored.
 *    - name: "UpdateUser"
 *      execute.limit: -1, # If the rate<0, the method will be ignored
 *    - name: "DeleteUser"
 *      execute.limit.rejected.handle: "customHandler" # Using the custom handler to do something when the request was rejected.
 *    - name: "AddUser"
 * From the example, the configuration in service-level is 200, and the configuration of method GetUser is 20.
 * it means that, the GetUser will be counted separately.
 * The configuration of method UpdateUser is -1, so the invocation for it will not be counted.
 * So the method DeleteUser and method AddUser will be limited by service-level configuration.
 * Sometimes we want to do something, like log the request or return default value when the request is over limitation.
 * Then you can implement the RejectedExecutionHandler interface and register it by invoking SetRejectedExecutionHandler.
 */
type ExecuteLimitFilter struct {
	executeState *concurrent.Map
}

// ExecuteState ...
type ExecuteState struct {
	concurrentCount int64
}

// Invoke ...
func (ef *ExecuteLimitFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
	methodConfigPrefix := "methods." + invocation.MethodName() + "."
	ivkURL := invoker.GetUrl()
	limitTarget := ivkURL.ServiceKey()
	limitRateConfig := constant.DEFAULT_EXECUTE_LIMIT

	methodLevelConfig := ivkURL.GetParam(methodConfigPrefix+constant.EXECUTE_LIMIT_KEY, "")
	if len(methodLevelConfig) > 0 {
		// we have the method-level configuration
		limitTarget = limitTarget + "#" + invocation.MethodName()
		limitRateConfig = methodLevelConfig
	} else {
		limitRateConfig = ivkURL.GetParam(constant.EXECUTE_LIMIT_KEY, constant.DEFAULT_EXECUTE_LIMIT)
	}

	limitRate, err := strconv.ParseInt(limitRateConfig, 0, 0)
	if err != nil {
		logger.Errorf("The configuration of execute.limit is invalid: %s", limitRateConfig)
		return &protocol.RPCResult{}
	}

	if limitRate < 0 {
		return invoker.Invoke(ctx, invocation)
	}

	state, _ := ef.executeState.LoadOrStore(limitTarget, &ExecuteState{
		concurrentCount: 0,
	})

	concurrentCount := state.(*ExecuteState).increase()
	defer state.(*ExecuteState).decrease()
	if concurrentCount > limitRate {
		logger.Errorf("The invocation was rejected due to over the execute limitation, url: %s ", ivkURL.String())
		rejectedHandlerConfig := ivkURL.GetParam(methodConfigPrefix+constant.EXECUTE_REJECTED_EXECUTION_HANDLER_KEY,
			ivkURL.GetParam(constant.EXECUTE_REJECTED_EXECUTION_HANDLER_KEY, constant.DEFAULT_KEY))
		return extension.GetRejectedExecutionHandler(rejectedHandlerConfig).RejectedExecution(ivkURL, invocation)
	}

	return invoker.Invoke(ctx, invocation)
}

// OnResponse ...
func (ef *ExecuteLimitFilter) OnResponse(_ context.Context, result protocol.Result, _ protocol.Invoker, _ protocol.Invocation) protocol.Result {
	return result
}

func (state *ExecuteState) increase() int64 {
	return atomic.AddInt64(&state.concurrentCount, 1)
}

func (state *ExecuteState) decrease() {
	atomic.AddInt64(&state.concurrentCount, -1)
}

var executeLimitOnce sync.Once
var executeLimitFilter *ExecuteLimitFilter

// GetExecuteLimitFilter ...
func GetExecuteLimitFilter() filter.Filter {
	executeLimitOnce.Do(func() {
		executeLimitFilter = &ExecuteLimitFilter{
			executeState: concurrent.NewMap(),
		}
	})
	return executeLimitFilter
}
