package com.highdatas.mdm.pojo.kettle;

import com.alibaba.druid.pool.DruidDataSource;
import com.highdatas.mdm.util.Constant;
import com.highdatas.mdm.util.DbUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.sql.*;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by LF on 2017/4/18.
 */
@ConfigurationProperties(prefix = "master.unbigdata.db")
@Component
public class UnBigDataDataSourceInfo implements DataSourceInfo{
  @Autowired
  private DataSource dataSource;

  @Value("${master.unbigdata.db.port}")
  private String dbPort;
  
  @Value("${master.unbigdata.db.schema}")
  private String dbName;
	
  @Value("${master.unbigdata.db.type}")
  private String dbType;
  
  @Value("${master.unbigdata.db.host}")
  private String dbHostName;

  @Value("${master.unbigdata.db.url}")
  private String dbUrl;

  @Value("${spring.datasource.username}")
  private String username;
 
  @Value("${spring.datasource.password}")
  private String password;
 
  @Value("${spring.datasource.driver-class-name}")
  private String driverClassName;
  
  private DruidDataSource datasource;
  
  public String getDbPort() {
	return dbPort;
  }

  public void setDbPort(String dbPort) {
	this.dbPort = dbPort;
  }

  public String getDbName() {
	return dbName;
  }

  public void setDbName(String dbName) {
	this.dbName = dbName;
  }

  public String getDbHostName() {
	return dbHostName;
  }

  public void setDbHostName(String dbHostName) {
	this.dbHostName = dbHostName;
  }

  public String getDbType() {
	return dbType;
  }

  public void setDbType(String dbType) {
	this.dbType = dbType;
  }

  public String getDbUrl() {
    return dbUrl;
  }

  public void setDbUrl(String dbUrl) {
    this.dbUrl = dbUrl;
  }
 
  public String getUsername() {
    return username;
  }
 
  public void setUsername(String username) {
    this.username = username;
  }
 
  public String getPassword() {
    return password;
  }
 
  public void setPassword(String password) {
    this.password = password;
  }
 
  public String getDriverClassName() {
    return driverClassName;
  }
 
  public void setDriverClassName(String driverClassName) {
    this.driverClassName = driverClassName;
  }


  @Override
  public boolean createTable(String assembleTempTableName, List<String> fieldList) {
    String fieldStr = fieldList.stream().map(s -> MessageFormat.format(Constant.CreateFieldMysql,s)).collect(Collectors.joining(Constant.COMMA));
    String create_sql = MessageFormat.format(Constant.CreateTableMysql, assembleTempTableName, fieldStr);
    Connection conn = null;
    try {
      conn = conn();
      PreparedStatement preparedStatement = conn.prepareStatement(create_sql);
      preparedStatement.execute();
      return true;
    } catch (SQLException e) {
      e.printStackTrace();
      return false;
    }
    finally {
      if (conn != null) {
        try {
          conn.close();
        } catch (SQLException e) {
          e.printStackTrace();
          return false;
        }
      }
    }
  }

  @Override
  public boolean checkFieldList(String tableName, List<String> fieldList) {
      Connection conn = null;
    try {

        conn = conn();
        PreparedStatement preparedStatement = conn.prepareStatement(MessageFormat.format(Constant.selectFieldSqlMysqlTemplate, tableName));
        ResultSet resultSet = preparedStatement.executeQuery();
        ResultSetMetaData metaData = resultSet.getMetaData();
        int columnCount = metaData.getColumnCount();
        List<String> tableFieldList = new ArrayList<>();
        for (int i = 1; i <= columnCount; i++) {
            tableFieldList.add(metaData.getColumnLabel(i)) ;
        }
        return  tableFieldList.containsAll(fieldList);
    } catch (SQLException e) {
      e.printStackTrace();
        return false;
    }finally {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
                return false;
            }
        }
    }


  }

  @Override
  public boolean checkTableExists(String assembleTempTableName) {
      Connection conn = null;
      try {
          conn = conn();
          PreparedStatement preparedStatement = conn.prepareStatement(MessageFormat.format(Constant.checkTableByNameBySchema, DbUtils.quotedStr(this.dbName), DbUtils.quotedStr(assembleTempTableName)));
          ResultSet resultSet = preparedStatement.executeQuery();
          resultSet.last();
          int row = resultSet.getRow();
          if (row > 0) {
              return true;
          }else {
              return false;
          }
      } catch (SQLException e) {
          e.printStackTrace();
          return false;
      }finally {
          if (conn != null) {
              try {
                  conn.close();
              } catch (SQLException e) {
                  e.printStackTrace();
                  return false;
              }
          }
      }

  }

    @Override
    public List<String> getFieldsFromTable(String tableName) {
        Connection conn = null;
        try {
            conn = conn();
            PreparedStatement preparedStatement = conn.prepareStatement(MessageFormat.format(Constant.selectFieldSqlMysqlTemplate, tableName));
            ResultSet resultSet = preparedStatement.executeQuery();
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            List<String> tableFieldList = new ArrayList<>();
            for (int i = 1; i <= columnCount; i++) {
                tableFieldList.add(metaData.getColumnLabel(i)) ;
            }
            return tableFieldList;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                    return null;
                }
            }
        }
    }

    @Bean
  @Primary
  public Connection conn() throws SQLException {
	  return dataSource.getConnection();
  }

    @Override
    public boolean truncateData(String tempTableName) {
        boolean exists = checkTableExists(tempTableName);
        if (!exists) {
            return false;
        }
        String truncateData = MessageFormat.format(Constant.truncateTableMysql, tempTableName);
        Connection conn = null;
        try {
            conn = conn();
            PreparedStatement preparedStatement = conn.prepareStatement(truncateData);
            preparedStatement.execute();
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
        finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                    return false;
                }
            }
        }
    }

    @Override
    public boolean dropData(String tempTableName) {
        boolean exists = checkTableExists(tempTableName);
        if (!exists) {
            return true;
        }
        String truncateData = MessageFormat.format(Constant.DropTableMysql, tempTableName);
        Connection conn = null;
        try {
            conn = conn();
            PreparedStatement preparedStatement = conn.prepareStatement(truncateData);
            preparedStatement.execute();
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
        finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                    return false;
                }
            }
        }
    }

}