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

import (
	"strings"
)

import (
	gxset "github.com/dubbogo/gost/container/set"
)

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/config_center"
	"dubbo.apache.org/dubbo-go/v3/config_center/parser"
)

func init() {
	extension.SetDefaultConfigurator(newConfigurator)
}

func newConfigurator(url *common.URL) config_center.Configurator {
	return &overrideConfigurator{configuratorUrl: url}
}

type overrideConfigurator struct {
	configuratorUrl *common.URL
}

func (c *overrideConfigurator) GetUrl() *common.URL {
	return c.configuratorUrl
}

func (c *overrideConfigurator) Configure(url *common.URL) {
	// remove configuratorUrl some param that can not be configured
	if c.configuratorUrl.GetParam(constant.EnabledKey, "true") == "false" || len(c.configuratorUrl.Location) == 0 {
		return
	}

	// branch for version 2.7.x
	apiVersion := c.configuratorUrl.GetParam(constant.ConfigVersionKey, "")
	if len(apiVersion) != 0 {
		var host string
		currentSide := url.GetParam(constant.SideKey, "")
		configuratorSide := c.configuratorUrl.GetParam(constant.SideKey, "")
		if currentSide == configuratorSide && common.DubboRole[common.CONSUMER] == currentSide {
			host = common.GetLocalIp()
		} else if currentSide == configuratorSide && common.DubboRole[common.PROVIDER] == currentSide {
			host = url.Ip
		}

		if strings.HasPrefix(apiVersion, constant.APIVersion) {
			c.configureIfMatchV3(host, url)
		} else {
			c.configureIfMatch(host, url)
		}
	} else {
		// branch for version 2.6.x and less
		c.configureDeprecated(url)
	}
}

// configureIfMatch
func (c *overrideConfigurator) configureIfMatchV3(host string, url *common.URL) {
	conditionKeys := getConditionKeys()
	if matcher, ok := c.configuratorUrl.GetAttribute(constant.MatchCondition); ok {
		conditionMatcher := matcher.(*parser.ConditionMatch)
		if conditionMatcher.IsMatch(host, url) {
			configUrl := c.configuratorUrl.CloneExceptParams(conditionKeys)
			url.SetParams(configUrl.GetParams())
		}
	}
}

func (c *overrideConfigurator) configureDeprecated(url *common.URL) {
	// If override url has port, means it is a provider address. We want to control a specific provider with this override url, it may take effect on the specific provider instance or on consumers holding this provider instance.
	if c.configuratorUrl.Port != "0" {
		if url.Port == c.configuratorUrl.Port {
			c.configureIfMatch(url.Ip, url)
		}
	} else {
		// override url don't have a port, means the ip override url specify is a consumer address or 0.0.0.0
		// 1.If it is a consumer ip address, the intention is to control a specific consumer instance, it must takes effect at the consumer side, any provider received this override url should ignore;
		// 2.If the ip is 0.0.0.0, this override url can be used on consumer, and also can be used on provider
		if url.GetParam(constant.SideKey, "") == common.DubboRole[common.CONSUMER] {
			localIP := common.GetLocalIp()
			c.configureIfMatch(localIP, url)
		} else {
			c.configureIfMatch(constant.AnyHostValue, url)
		}
	}
}

func (c *overrideConfigurator) configureIfMatchInternal(url *common.URL) {
	configApp := c.configuratorUrl.GetParam(constant.ApplicationKey, c.configuratorUrl.Username)
	currentApp := url.GetParam(constant.ApplicationKey, url.Username)
	if len(configApp) == 0 || constant.AnyValue == configApp || configApp == currentApp {
		conditionKeys := getConditionKeys()
		returnUrl := false
		c.configuratorUrl.RangeParams(func(k, _ string) bool {
			value := c.configuratorUrl.GetParam(k, "")
			if strings.HasPrefix(k, "~") || k == constant.ApplicationKey || k == constant.SideKey {
				conditionKeys.Add(k)
				if len(value) != 0 && value != constant.AnyValue && value != url.GetParam(strings.TrimPrefix(k, "~"), "") {
					returnUrl = true
					return false
				}
			}
			return true
		})
		if returnUrl {
			return
		}
		configUrl := c.configuratorUrl.CloneExceptParams(conditionKeys)
		url.SetParams(configUrl.GetParams())
	}
}

// configureIfMatch translate from java, compatible rules in java
func (c *overrideConfigurator) configureIfMatch(host string, url *common.URL) {
	if constant.AnyHostValue == c.configuratorUrl.Ip || host == c.configuratorUrl.Ip {
		providers := c.configuratorUrl.GetParam(constant.OverrideProvidersKey, "")
		if len(providers) == 0 || strings.Contains(providers, url.Location) || strings.Contains(providers, constant.AnyHostValue) {
			c.configureIfMatchInternal(url)
		}
	}
}

func getConditionKeys() *gxset.HashSet {
	conditionKeys := gxset.NewSet()
	conditionKeys.Add(constant.CategoryKey)
	conditionKeys.Add(constant.CheckKey)
	conditionKeys.Add(constant.EnabledKey)
	conditionKeys.Add(constant.GroupKey)
	conditionKeys.Add(constant.VersionKey)
	conditionKeys.Add(constant.ApplicationKey)
	conditionKeys.Add(constant.SideKey)
	conditionKeys.Add(constant.ConfigVersionKey)
	conditionKeys.Add(constant.CompatibleConfigKey)
	return conditionKeys
}
