/*
 * 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 org.apache.servicecomb.core.provider.consumer;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.inject.Inject;

import org.apache.servicecomb.core.Const;
import org.apache.servicecomb.core.ConsumerProvider;
import org.apache.servicecomb.core.definition.schema.ConsumerSchemaFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicStringProperty;

@Component
public class ConsumerProviderManager {
  @Autowired(required = false)
  private List<ConsumerProvider> consumerProviderList = Collections.emptyList();

  @Inject
  private ConsumerSchemaFactory consumerSchemaFactory;

  // key为微服务名
  private volatile Map<String, ReferenceConfig> referenceConfigMap = new ConcurrentHashMap<>();

  public void setConsumerSchemaFactory(ConsumerSchemaFactory consumerSchemaFactory) {
    this.consumerSchemaFactory = consumerSchemaFactory;
  }

  public void init() throws Exception {
    for (ConsumerProvider provider : consumerProviderList) {
      provider.init();
    }
  }

  public ReferenceConfig createReferenceConfig(String microserviceName, String microserviceVersion,
      String transport) {
    return new ReferenceConfig(consumerSchemaFactory, microserviceName, microserviceVersion, transport);
  }

  public ReferenceConfig getReferenceConfig(String microserviceName) {
    ReferenceConfig config = referenceConfigMap.get(microserviceName);
    if (config == null) {
      synchronized (this) {
        config = referenceConfigMap.get(microserviceName);
        if (config == null) {
          String key = "cse.references." + microserviceName;
          DynamicStringProperty versionRule = DynamicPropertyFactory.getInstance()
              .getStringProperty(key + ".version-rule",
                  DynamicPropertyFactory.getInstance()
                      .getStringProperty("cse.references.version-rule", Const.VERSION_RULE_LATEST)
                      .getValue());
          DynamicStringProperty transport =
              DynamicPropertyFactory.getInstance().getStringProperty(key + ".transport",
                  DynamicPropertyFactory.getInstance()
                      .getStringProperty("cse.references.transport",
                          Const.ANY_TRANSPORT)
                      .getValue());

          config = new ReferenceConfig(consumerSchemaFactory, microserviceName, versionRule.getValue(),
              transport.getValue());
          referenceConfigMap.put(microserviceName, config);
        }
      }
    }

    return config;
  }

  // 只用于测试场景
  public ReferenceConfig setTransport(String microserviceName, String transport) {
    ReferenceConfig config = getReferenceConfig(microserviceName);
    config.setTransport(transport);

    return config;
  }
}
