package com.chenyang.nse.bussiness.tools.dataprocess.hive.hdfs.operator;

import com.chenyang.nse.bussiness.entity.orm.table.core.TCoreDatasystem;
import com.chenyang.nse.bussiness.tools.dataprocess.hive.TdhHiveTool;
import com.chenyang.nse.bussiness.tools.dataprocess.hive.hdfs.HdfsFileInfo;
import com.chenyang.nse.bussiness.tools.dataprocess.hive.hdfs.TableInfo;
import com.chenyang.nse.bussiness.tools.dataprocess.hive.hdfs.format.HdfsItemIterator;
import com.chenyang.nse.bussiness.tools.jdbc.JdbcTool;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.security.UserGroupInformation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LdapHdfsOperator extends HdfsOperator {
   private static final Logger LOGGER = LoggerFactory.getLogger(KeberosHdfsOperator.class);
   String nameService = "hdfs://nameservice1";
   public TCoreDatasystem dataSystem;
   private Configuration authConfig;
   private Configuration readConfig;

   public LdapHdfsOperator(Connection connection, Properties properties, TableInfo table) {
      super(connection, properties, table);
      this.loadProperties();
   }

   public void prepare(String schema, String table) throws Exception {
   }

   private void loadProperties() {
      if (this.properties != null && this.properties.size() != 0) {
         String hdfsNameService = this.properties.getProperty("web.hdfs.name-service");
         if (hdfsNameService != null && hdfsNameService.length() > 0) {
            this.nameService = hdfsNameService;
         }

      }
   }

   private Configuration getLoginConfiguration() {
      if (this.authConfig != null) {
         return this.authConfig;
      } else {
         String xmlpath = this.dataSystem.getXmlpath();
         String krb5conf = this.dataSystem.getKrb5conf();
         Configuration conf = new Configuration();
         conf.set("hadoop.security.authentication", "Kerberos");
         conf.set("fs.hdfs.impl", DistributedFileSystem.class.getName());
         System.setProperty("java.security.krb5.conf", this.dataSystem.getKrb5conf());
         System.setProperty("sun.security.krb5.debug", "true");
         this.authConfig = conf;
         return this.authConfig;
      }
   }

   private Configuration getReadWriteConfiguration() {
      if (this.authConfig == null) {
         this.readConfig = this.getLoginConfiguration();
      }

      String xmlpath = this.dataSystem.getXmlpath();
      String krb5conf = this.dataSystem.getKrb5conf();
      this.readConfig.set("hadoop.security.authentication", "Kerberos");
      this.readConfig.set("fs.hdfs.impl", DistributedFileSystem.class.getName());
      System.setProperty("java.security.krb5.conf", this.dataSystem.getKrb5conf());
      System.setProperty("sun.security.krb5.debug", "true");
      return this.readConfig;
   }

   protected void authenticate() throws IOException {
      Configuration loginConfiguration = this.getLoginConfiguration();
      UserGroupInformation.setConfiguration(loginConfiguration);
      UserGroupInformation.loginUserFromKeytab(this.dataSystem.getHdfsKeberos(), this.dataSystem.getXmlpath() + "/hdfs.keytab");
   }

   public List<HdfsFileInfo> listFiles(String schema, String table, String location) throws IOException {
      if (location == null) {
         location = this.getTableLocation(schema, table);
      }

      if (location != null && location.length() != 0) {
         String xmlpath = this.dataSystem.getXmlpath();
         String krb5conf = this.dataSystem.getKrb5conf();
         Configuration conf = this.getReadWriteConfiguration();
         String inFilePath = location;
         if (location == null || location.length() == 0) {
            inFilePath = JdbcTool.queryHdfsLocationForTDH(this.connection, schema, table);
         }

         String hdfsPath = inFilePath.replaceFirst(this.nameService, "");
         List<HashMap<String, String>> hdfsList = TdhHiveTool.getHdfsList(xmlpath, this.dataSystem.getLoginprincipal(), inFilePath, hdfsPath);
         List<HdfsFileInfo> files = new ArrayList();

         for(HashMap<String, String> entry : hdfsList) {
            HdfsFileInfo file = new HdfsFileInfo();
            file.setName((String)entry.get("name"));
            file.setFullName((String)entry.get("path"));
            file.setLength((String)entry.get("length"));
            file.setBlockSize((String)entry.get("blocksize"));
            file.setGroup((String)entry.get("group"));
            file.setPermission((String)entry.get("permission"));
            file.setOwner((String)entry.get("owner"));
            files.add(file);
         }

         return files;
      } else {
         return null;
      }
   }

   public InputStream loadFile(String schema, String table, String location) throws IOException {
      if (location != null && location.length() != 0) {
         Configuration conf = this.getReadWriteConfiguration();
         FileSystem fs = FileSystem.get(conf);
         Path p = new Path(location);
         FSDataInputStream fis = fs.open(p);
         return fis;
      } else {
         return null;
      }
   }

   public HdfsItemIterator loadFileIter(String schema, String table, String location) throws IOException {
      return null;
   }

   public OutputStream createFile(String schema, String table, String location) throws IOException {
      if (location != null && location.length() != 0) {
         Configuration conf = this.getReadWriteConfiguration();
         FileSystem fs = FileSystem.get(conf);
         Path p = new Path(location);
         FSDataOutputStream output = fs.create(p, true);
         return output;
      } else {
         return null;
      }
   }

   public void saveBatch(String schema, String table, String location, OutputStream stream) throws Exception {
      stream.flush();
   }

   public void fininshed(String schema, String table) throws Exception {
   }

   public void closeFile(String schema, String table, String location) throws Exception {
   }

   public void deleteFile(String schema, String table, String location) throws IOException, URISyntaxException {
      Configuration conf = this.getReadWriteConfiguration();
      FileSystem fs = FileSystem.get(conf);
      Path p1 = new Path(location);
      fs.delete(p1);
   }

   public void rename(String schema, String table, String location, String newname) throws Exception {
      if (location != null && location.length() != 0) {
         if (newname != null && newname.length() != 0) {
            Configuration conf = this.getReadWriteConfiguration();
            FileSystem fs = FileSystem.get(conf);
            Path p1 = new Path(location);
            Path p2 = new Path(newname);
            fs.rename(p2, p1);
         } else {
            throw new Exception("修改后的文件名为空");
         }
      } else {
         throw new Exception("被修改的文件名为空");
      }
   }
}
