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

import (
	"fmt"
	"log"
	"os"
	"time"
)

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

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

var (
	consumerConfig    *ConsumerConfig
	providerConfig    *ProviderConfig
	metricConfig      *MetricConfig
	applicationConfig *ApplicationConfig
	maxWait           = 3
	confRouterFile    string
)

// loaded consumer & provider config from xxx.yml, and log config from xxx.xml
// Namely: dubbo.consumer.xml & dubbo.provider.xml in java dubbo
func init() {
	var (
		confConFile string
		confProFile string
	)

	confConFile = os.Getenv(constant.CONF_CONSUMER_FILE_PATH)
	confProFile = os.Getenv(constant.CONF_PROVIDER_FILE_PATH)
	confRouterFile = os.Getenv(constant.CONF_ROUTER_FILE_PATH)

	if errCon := ConsumerInit(confConFile); errCon != nil {
		log.Printf("[consumerInit] %#v", errCon)
		consumerConfig = nil
	}

	if errPro := ProviderInit(confProFile); errPro != nil {
		log.Printf("[providerInit] %#v", errPro)
		providerConfig = nil
	}
}

func checkRegistries(registries map[string]*RegistryConfig, singleRegistry *RegistryConfig) {
	if len(registries) == 0 && singleRegistry != nil {
		registries[constant.DEFAULT_KEY] = singleRegistry
	}
}

func checkApplicationName(config *ApplicationConfig) {
	if config == nil || len(config.Name) == 0 {
		errMsg := "application config must not be nil, pls check your configuration"
		logger.Errorf(errMsg)
		panic(errMsg)
	}
}

// Load Dubbo Init
func Load() {

	// init router
	if confRouterFile != "" {
		if errPro := RouterInit(confRouterFile); errPro != nil {
			log.Printf("[routerConfig init] %#v", errPro)
		}
	}

	// reference config
	if consumerConfig == nil {
		logger.Warnf("consumerConfig is nil!")
	} else {
		// init other consumer config
		conConfigType := consumerConfig.ConfigType
		for key, value := range extension.GetDefaultConfigReader() {
			if conConfigType == nil {
				if v, ok := conConfigType[key]; ok {
					value = v
				}
			}
			if err := extension.GetConfigReaders(value).ReadConsumerConfig(consumerConfig.fileStream); err != nil {
				logger.Errorf("ReadConsumerConfig error: %#v for %s", perrors.WithStack(err), value)
			}
		}

		metricConfig = consumerConfig.MetricConfig
		applicationConfig = consumerConfig.ApplicationConfig

		checkApplicationName(consumerConfig.ApplicationConfig)
		if err := configCenterRefreshConsumer(); err != nil {
			logger.Errorf("[consumer config center refresh] %#v", err)
		}
		checkRegistries(consumerConfig.Registries, consumerConfig.Registry)
		for key, ref := range consumerConfig.References {
			if ref.Generic {
				genericService := NewGenericService(key)
				SetConsumerService(genericService)
			}
			rpcService := GetConsumerService(key)
			if rpcService == nil {
				logger.Warnf("%s does not exist!", key)
				continue
			}
			ref.id = key
			ref.Refer(rpcService)
			ref.Implement(rpcService)
		}

		//wait for invoker is available, if wait over default 3s, then panic
		var count int
		checkok := true
		for {
			for _, refconfig := range consumerConfig.References {
				if (refconfig.Check != nil && *refconfig.Check) ||
					(refconfig.Check == nil && consumerConfig.Check != nil && *consumerConfig.Check) ||
					(refconfig.Check == nil && consumerConfig.Check == nil) { //default to true

					if refconfig.invoker != nil &&
						!refconfig.invoker.IsAvailable() {
						checkok = false
						count++
						if count > maxWait {
							errMsg := fmt.Sprintf("Failed to check the status of the service %v . No provider available for the service to the consumer use dubbo version %v", refconfig.InterfaceName, constant.Version)
							logger.Error(errMsg)
							panic(errMsg)
						}
						time.Sleep(time.Second * 1)
						break
					}
					if refconfig.invoker == nil {
						logger.Warnf("The interface %s invoker not exist , may you should check your interface config.", refconfig.InterfaceName)
					}
				}
			}
			if checkok {
				break
			}
			checkok = true
		}
	}

	// service config
	if providerConfig == nil {
		logger.Warnf("providerConfig is nil!")
	} else {
		// init other provider config
		proConfigType := providerConfig.ConfigType
		for key, value := range extension.GetDefaultConfigReader() {
			if proConfigType != nil {
				if v, ok := proConfigType[key]; ok {
					value = v
				}
			}
			if err := extension.GetConfigReaders(value).ReadProviderConfig(providerConfig.fileStream); err != nil {
				logger.Errorf("ReadProviderConfig error: %#v for %s", perrors.WithStack(err), value)
			}
		}

		// so, you should know that the consumer's config will be override
		metricConfig = providerConfig.MetricConfig
		applicationConfig = providerConfig.ApplicationConfig

		checkApplicationName(providerConfig.ApplicationConfig)
		if err := configCenterRefreshProvider(); err != nil {
			logger.Errorf("[provider config center refresh] %#v", err)
		}
		checkRegistries(providerConfig.Registries, providerConfig.Registry)
		for key, svs := range providerConfig.Services {
			rpcService := GetProviderService(key)
			if rpcService == nil {
				logger.Warnf("%s does not exist!", key)
				continue
			}
			svs.id = key
			svs.Implement(rpcService)
			if err := svs.Export(); err != nil {
				panic(fmt.Sprintf("service %s export failed! ", key))
			}
		}
	}
	// init the shutdown callback
	GracefulShutdownInit()
}

// GetRPCService get rpc service for consumer
func GetRPCService(name string) common.RPCService {
	return consumerConfig.References[name].GetRPCService()
}

// RPCService create rpc service for consumer
func RPCService(service common.RPCService) {
	consumerConfig.References[service.Reference()].Implement(service)
}

// GetMetricConfig find the MetricConfig
// if it is nil, create a new one
func GetMetricConfig() *MetricConfig {
	if metricConfig == nil {
		metricConfig = &MetricConfig{}
	}
	return metricConfig
}

// GetApplicationConfig find the application config
// if not, we will create one
// Usually applicationConfig will be initialized when system start
func GetApplicationConfig() *ApplicationConfig {
	if applicationConfig == nil {
		applicationConfig = &ApplicationConfig{}
	}
	return applicationConfig
}

// GetProviderConfig find the provider config
// if not found, create new one
func GetProviderConfig() ProviderConfig {
	if providerConfig == nil {
		logger.Warnf("providerConfig is nil!")
		return ProviderConfig{}
	}
	return *providerConfig
}

// GetConsumerConfig find the consumer config
// if not found, create new one
func GetConsumerConfig() ConsumerConfig {
	if consumerConfig == nil {
		logger.Warnf("consumerConfig is nil!")
		return ConsumerConfig{}
	}
	return *consumerConfig
}
