package com.friday.dynamic.core;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

@Slf4j
@Data
public class DubboLoader {

    private ApplicationConfig applicationConfig;

    public Map<String, Object> refresh(List<BizDubboConfig> dubboConfigList, Map<String, Class> dubboClassMap) {
        Map<String, Object> dubboServiceBeanMap = new HashMap<>();
        for(BizDubboConfig config : dubboConfigList){
            String beanName = getDefaultBeanName(config.getInterfaceFullyQualifiedName());

            Optional<Object> referenceBean = createDubboServiceBean(config, beanName, dubboClassMap.get(config.getInterfaceFullyQualifiedName()));
            referenceBean.ifPresent(o -> dubboServiceBeanMap.put(beanName, o));
        }
        return dubboServiceBeanMap;
    }

    private Optional<Object> createDubboServiceBean(BizDubboConfig config, String beanName, Class dubboClass) {
        if(StringUtils.isEmpty(beanName) || Objects.isNull(dubboClass)){
            log.error("创建Dubbo实例失败：缺失必要的配置信息");
            return Optional.empty();
        }
        // 引用远程服务 todo reference放入缓存
        try {
            ReferenceConfig<?> reference = new ReferenceConfig<>(); //此实例很重，封装了与注册中心的连接以及与提供者的连接，请自行缓存，否则可能造成内存和连接泄漏
            reference.setApplication(applicationConfig);
            reference.setRegistry(this.createRegistryConfig(config));
            reference.setInterface(dubboClass);
            reference.setVersion(config.getVersion());
            reference.setId(beanName);
            reference.setCheck(config.getCheck());
            reference.setTimeout(config.getTimeout());
            reference.setRetries(config.getRetryTime());
            return Optional.of(reference.get());
        } catch (Exception e){
            log.error("创建Dubbo实例异常", e);
            return Optional.empty();
        }
    }

    private RegistryConfig createRegistryConfig(BizDubboConfig config) {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress(config.getAddress());
        registryConfig.setTimeout(config.getTimeout());
        return registryConfig;
    }

    private String getDefaultBeanName(String fullyQualifiedName){
        String beanName = fullyQualifiedName.substring(fullyQualifiedName.lastIndexOf(".") + 1);
        return StringUtils.uncapitalize(beanName);
    }

}