package com.scm.contract.properties;

import java.io.IOException;
import java.util.Optional;
import java.util.Properties;
import java.util.stream.Stream;

import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ExecutorType;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

@ConfigurationProperties(prefix = "mybatis.config1")
public class MybatisWzhtProperties {


	  private static final ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();

	  /**
	   * Location of MyBatis xml config file.
	   */
	  private String configLocation;

	  /**
	   * Locations of MyBatis mapper files.
	   */
	  private String[] mapperLocations;

	  /**
	   * Packages to search type aliases. (Package delimiters are ",; \t\n")
	   */
	  private String typeAliasesPackage;

	  /**
	   * The super class for filtering type alias.
	   * If this not specifies, the MyBatis deal as type alias all classes that searched from typeAliasesPackage.
	   */
	  private Class<?> typeAliasesSuperType;

	  /**
	   * Packages to search for type handlers. (Package delimiters are ",; \t\n")
	   */
	  private String typeHandlersPackage;

	  /**
	   * Indicates whether perform presence check of the MyBatis xml config file.
	   */
	  private boolean checkConfigLocation = false;

	  /**
	   * Execution mode for {@link org.mybatis.spring.SqlSessionTemplate}.
	   */
	  private ExecutorType executorType;

	  /**
	   * Externalized properties for MyBatis configuration.
	   */
	  private Properties configurationProperties;

	  /**
	   * A Configuration object for customize default settings. If {@link #configLocation}
	   * is specified, this property is not used.
	   */
	  @NestedConfigurationProperty
	  private Configuration configuration;

	  /**
	   * @since 1.1.0
	   */
	  public String getConfigLocation() {
	    return this.configLocation;
	  }

	  /**
	   * @since 1.1.0
	   */
	  public void setConfigLocation(String configLocation) {
	    this.configLocation = configLocation;
	  }

	  public String[] getMapperLocations() {
	    return this.mapperLocations;
	  }

	  public void setMapperLocations(String[] mapperLocations) {
	    this.mapperLocations = mapperLocations;
	  }

	  public String getTypeHandlersPackage() {
	    return this.typeHandlersPackage;
	  }

	  public void setTypeHandlersPackage(String typeHandlersPackage) {
	    this.typeHandlersPackage = typeHandlersPackage;
	  }

	  public String getTypeAliasesPackage() {
	    return this.typeAliasesPackage;
	  }

	  public void setTypeAliasesPackage(String typeAliasesPackage) {
	    this.typeAliasesPackage = typeAliasesPackage;
	  }

	  /**
	   * @since 1.3.3
	   */
	  public Class<?> getTypeAliasesSuperType() {
	    return typeAliasesSuperType;
	  }

	  /**
	   * @since 1.3.3
	   */
	  public void setTypeAliasesSuperType(Class<?> typeAliasesSuperType) {
	    this.typeAliasesSuperType = typeAliasesSuperType;
	  }

	  public boolean isCheckConfigLocation() {
	    return this.checkConfigLocation;
	  }

	  public void setCheckConfigLocation(boolean checkConfigLocation) {
	    this.checkConfigLocation = checkConfigLocation;
	  }

	  public ExecutorType getExecutorType() {
	    return this.executorType;
	  }

	  public void setExecutorType(ExecutorType executorType) {
	    this.executorType = executorType;
	  }

	  /**
	   * @since 1.2.0
	   */
	  public Properties getConfigurationProperties() {
	    return configurationProperties;
	  }

	  /**
	   * @since 1.2.0
	   */
	  public void setConfigurationProperties(Properties configurationProperties) {
	    this.configurationProperties = configurationProperties;
	  }

	  public Configuration getConfiguration() {
	    return configuration;
	  }

	  public void setConfiguration(Configuration configuration) {
	    this.configuration = configuration;
	  }

	  public Resource[] resolveMapperLocations() {
	    return Stream.of(Optional.ofNullable(this.mapperLocations).orElse(new String[0]))
	        .flatMap(location -> Stream.of(getResources(location)))
	        .toArray(Resource[]::new);
	  }

	  private Resource[] getResources(String location) {
	    try {
	      return resourceResolver.getResources(location);
	    } catch (IOException e) {
	      return new Resource[0];
	    }
	  }

}
