/*
 * 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.foundation.common.utils;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public final class BeanUtils {
  private static final Logger LOGGER = LoggerFactory.getLogger(BeanUtils.class);

  public static final String DEFAULT_BEAN_CORE_RESOURCE = "classpath*:META-INF/spring/scb-core-bean.xml";

  public static final String DEFAULT_BEAN_NORMAL_RESOURCE = "classpath*:META-INF/spring/*.bean.xml";

  public static final String[] DEFAULT_BEAN_RESOURCE = new String[] {DEFAULT_BEAN_CORE_RESOURCE
      , DEFAULT_BEAN_NORMAL_RESOURCE};

  public static final String SCB_SCAN_PACKAGE = "scb-scan-package";

  private static final String SCB_PACKAGE = "org.apache.servicecomb";

  private static ApplicationContext context;

  private BeanUtils() {
  }

  public static void init() {
    init(DEFAULT_BEAN_RESOURCE);
  }

  public static void init(String... configLocations) {
    prepareServiceCombScanPackage();

    Set<String> locationSet = new LinkedHashSet<>();
    addBeanLocation(locationSet, DEFAULT_BEAN_RESOURCE);
    addBeanLocation(locationSet, configLocations);
    context = new ClassPathXmlApplicationContext(locationSet.toArray(new String[0]));
  }

  public static void addBeanLocation(Set<String> locationSet, String... location) {
    Arrays.stream(location).forEach(loc -> addBeanLocation(locationSet, loc));
  }

  public static void addBeanLocation(Set<String> locationSet, String location) {
    if (location == null) {
      return;
    }

    location = location.trim();
    if (StringUtils.isNotEmpty(location)) {
      locationSet.add(location);
    }
  }

  private static void addItem(Set<String> set, String item) {
    for (String it : set) {
      if (item.startsWith(it)) {
        return;
      }
    }
    set.add(item);
  }

  public static void prepareServiceCombScanPackage() {
    Set<String> scanPackags = new LinkedHashSet<>();
    // add exists settings
    String exists = System.getProperty(SCB_SCAN_PACKAGE);
    if (exists != null) {
      for (String exist : exists.trim().split(",")) {
        if (!exist.isEmpty()) {
          addItem(scanPackags, exist.trim());
        }
      }
    }

    // ensure servicecomb package exist
    addItem(scanPackags, SCB_PACKAGE);

    // add main class package
    for (Class<?> mainClass : new Class<?>[] {JvmUtils.findMainClass(), JvmUtils.findMainClassByStackTrace()}) {
      if (mainClass != null && mainClass.getPackage() != null) {
        String pkg = mainClass.getPackage().getName();
        addItem(scanPackags, pkg);
      }
    }

    // finish
    String scbScanPackages = StringUtils.join(scanPackags, ",");
    System.setProperty(SCB_SCAN_PACKAGE, scbScanPackages);
    LOGGER.info("Scb scan package list: " + scbScanPackages);
  }

  public static ApplicationContext getContext() {
    return context;
  }

  public static void setContext(ApplicationContext applicationContext) {
    context = applicationContext;
  }

  /**
   * 不应该在业务流程中频繁调用，因为内部必然会加一个锁做互斥，会影响并发度
   */
  @SuppressWarnings("unchecked")
  public static <T> T getBean(String name) {
    return (T) context.getBean(name);
  }

  public static <T> Map<String, T> getBeansOfType(Class<T> type) {
    if (context == null) {
      // for some test case
      return Collections.emptyMap();
    }
    return context.getBeansOfType(type);
  }

  public static <T> T getBean(Class<T> type) {
    if (context == null) {
      // for some test case
      return null;
    }
    return context.getBean(type);
  }

  /**
   * Get the implemented class of the given instance
   * @param bean the instance to get implemented class from
   * @return the implemented class (if the checked class is proxied, return the ultimate target class)
   * @see org.springframework.aop.framework.AopProxyUtils#ultimateTargetClass
   */
  public static Class<?> getImplClassFromBean(Object bean) {
    return AopProxyUtils.ultimateTargetClass(bean);
  }

  public static <T extends SPIOrder & SPIEnabled> void addBeans(Class<T> cls, List<T> exists) {
    if (context == null) {
      return;
    }

    for (T instance : exists) {
      context.getAutowireCapableBeanFactory().autowireBean(instance);
    }
    for (T bean : context.getBeansOfType(cls).values()) {
      if (bean.enabled()) {
        exists.add(bean);
      }
    }
    exists.sort(Comparator.comparingInt(SPIOrder::getOrder));
  }
}
