package com.zy.ruralhouse.utils;

import com.zy.ruralhouse.mapper.RuralInfoMapper;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * @Author:pmy
 * @Description:
 * @Date:2020/7/29
 */
@Component
public class ZipUtil {
    @Resource
    private RuralInfoMapper ruralInfoMapper;
    /**
     * zip解压
     * @param srcFile        zip源文件
     * @param destDirPath     解压后的目标文件夹
     * @throws RuntimeException 解压失败会抛出运行时异常
     */
    public static String unZipFiles(File srcFile, String destDirPath,String flag) throws RuntimeException {
        long start = System.currentTimeMillis();
        String mdbFilePath=null;
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            throw new RuntimeException(srcFile.getPath() + "所指文件不存在");
        }
        // 开始解压
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(srcFile,"gbk");
            Enumeration<?> entries = zipFile.getEntries();
            List<String> filePathList=null;
            Map<String, Object> m = null;
            Map<String,String> mdata=null;
            while (entries.hasMoreElements()) {
                ZipEntry entry = (ZipEntry) entries.nextElement();
                String zipEntryName = entry.getName();
                if("sxsj".equals(flag)){
                    if(!zipEntryName.toLowerCase().endsWith(".mdb")) continue;
                }
                System.out.println("解压" + entry.getName());
                // 如果是文件夹,就创建个文件夹
                if (entry.isDirectory()) {
                    String dirPath = destDirPath + "/" + zipEntryName;
                    File dir = new File(dirPath);
                    dir.mkdirs();
                } else {
                    // 如果是文件,就先创建一个文件,然后用io流把内容copy过去
                    String filePath=destDirPath + "/" + zipEntryName;
                    File targetFile = new File(filePath);
                    // 保证这个文件的父文件夹必须要存在

                    if(!targetFile.getParentFile().exists()){
                        targetFile.getParentFile().mkdirs();
                    }
                    targetFile.createNewFile();
                    // 将压缩文件内容写入到这个文件中
                    InputStream is = zipFile.getInputStream(entry);
                    FileOutputStream fos = new FileOutputStream(targetFile);
                    int len;
                    byte[] buf = new byte[1024];
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                    }
                    // 关流顺序,先打开的后关闭
                    fos.close();
                    is.close();
                    //获取空间文件集合
                    String fileName=targetFile.getName();
//                    String namePre = fileName.substring(0, fileName.lastIndexOf("."));
//                    if(fileName.toLowerCase().endsWith(".dbf")){
//                        if(mdata==null){
//                            mdata=new HashMap<>();
//                            mdata.put("dbfPath",filePath);
//                        }
//                    }else if(fileName.toLowerCase().endsWith(".shp")){
//                        mdata.put("shpPath",filePath);
//                        m = new HashMap<>();
//                        m.put("id", namePre);
//                        m.put("type",namePre.toLowerCase().indexOf("zdjbxx")!=-1?"zdxx":"common");
//                        m.put("data", mdata);
//                        pathList.add(m);
//                        mdata=null;
//                        m=null;
//                    }
                    if (fileName.toLowerCase().endsWith(".mdb")) {
                        mdbFilePath = filePath;
                    }
                }
            }
            long end = System.currentTimeMillis();
            System.out.println("解压完成,耗时:" + (end - start) +" ms");
        } catch (Exception e) {
            throw new RuntimeException("unzip error from ZipUtils", e);
        } finally {
            if(zipFile != null){
                try {
                    zipFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return mdbFilePath;
    }
    /**
     * @param filePath
     * 临时文件的删除
     * 删除文件夹里面子目录
     * 再删除文件夹
     */
    public void deleteFiles(String filePath) {
        File file = new File(filePath);
        if ((!file.exists()) || (!file.isDirectory())) {
            System.out.println("file not exist");
            return;
        }
        String[] tempList = file.list();
        File temp = null;
        for (int i = 0; i < tempList.length; i++) {
            if (filePath.endsWith(File.separator)) {
                temp = new File(filePath + tempList[i]);
            }
            else {
                temp = new File(filePath + File.separator + tempList[i]);
            }
            if (temp.isFile()) {
                temp.delete();
            }
            if (temp.isDirectory()) {
                this.deleteFiles(filePath + "/" + tempList[i]);
            }
        }
        // 空文件的删除
        file.delete();
    }

    /**
     * @param desFile,fileList
     * 获取目录下所有文件,包括子文件夹下的文件
     */
    public List<File> getSubFiles(String  desFile, List<File> fileList) {
        File file = new File(desFile);
        File[] files = file.listFiles();
        for (File fileIndex : files) {
            if (!fileIndex.exists()) {
                throw new NullPointerException("Cannot find " + fileIndex);
            } else if (fileIndex.isFile()) {
                fileList.add(fileIndex);
            } else {
                if (fileIndex.isDirectory()) {
                    getSubFiles(fileIndex.getAbsolutePath(),fileList);
                }
            }
        }
        return fileList;
    }

    public Map<String,Map<String,List<File>>> getFiles(String path,String zddm,String unitId,Map<String,Map<String,List<File>>> o){
        File file = new File(path);
        File[] files = file.listFiles();
        for (File fileIndex : files) {
            if (!fileIndex.exists()) {
                throw new NullPointerException("Cannot find " + fileIndex);
            } else if(fileIndex.isDirectory()){
                    if(fileIndex.getName().contains(zddm)){
                        if(o==null || o.get(zddm) == null){
                            Map<String,List<File>> pf = new HashMap<>();
                            List<File> f = new ArrayList<>();
                            f=getSubFiles(fileIndex.getAbsolutePath()+"/zd_archives",f);
                            pf.put("宗地附件",f);
                            o.put(zddm,pf);
                        }
                        File mf= new File(fileIndex.getAbsolutePath());
                        File[] ms = mf.listFiles();
                        for(File tf:ms){
                            if(tf.getName().contains(unitId)){
                                Map<String,List<File>> uf = new HashMap<>();
                                File ff= new File(tf.getAbsolutePath());
                                File[] fs = ff.listFiles();
                                List<File> s = new ArrayList<>();
                                for(File zf:fs){
                                    if(zf.isFile()){
                                        s.add(zf);
                                        uf.put("房屋附件",s);
                                    }else if (zf.isDirectory()){
                                        if(zf.getName().contains("分户")){
                                            List<File> wf = new ArrayList<>();
                                            wf=getSubFiles(zf.getAbsolutePath(),wf);
                                            uf.put("分层分户图",wf);
                                        } else if(zf.getName().contains("其他")){
                                            List<File> wf = new ArrayList<>();
                                            wf=getSubFiles(zf.getAbsolutePath(),wf);
                                            uf.put("其他附件",wf);
                                        }else{
                                            getFiles(zf.getAbsolutePath(),zddm,unitId,o);
                                        }
                                    }
                                }
                                o.put(unitId,uf);
                            }else{
                                getFiles(tf.getAbsolutePath(),zddm,unitId,o);
                            }
                        }
                        break;
                    }else {
                        getFiles(fileIndex.getAbsolutePath(),zddm,unitId,o);
                    }
            }
        }
        return o;
    }


    public Map<String,Map<String,List<File>>> getFilesTwo(String path,String zddm,String unitId,Map<String,Map<String,List<File>>> o,Integer status) {
        File file = new File(path);
        File[] files = file.listFiles();
        if (files != null) {
            for (File fileIndex : files) {
                if (fileIndex.isDirectory()) {
                    if (fileIndex.getParent().contains("扫描档案")) {
                        File zd = new File(fileIndex.getAbsolutePath());
                        File[] zs = zd.listFiles();
                        for (File f : zs) {
                            if (f.getName().contains(zddm)) {
                                File mf = new File(f.getAbsolutePath());
                                File[] ms = mf.listFiles();
                                for (File tf : ms) {
                                    if (tf.getName().contains(unitId)) {
                                        //修改材料上传补录标志 补录的时候需要用
                                        if(status==4){
                                            ruralInfoMapper.updateCommitToBdcByZddm("3",zddm,unitId);
                                        }
                                        Map<String, List<File>> uf = new HashMap<>();
                                        File ff = new File(tf.getAbsolutePath());
                                        File[] fs = ff.listFiles();
                                        List<File> s = new ArrayList<>();
                                        for (File zf : fs) {
                                            if (zf.isFile()) {
                                                s.add(zf);
                                                uf.put("房屋附件", s);
                                            } else if (zf.isDirectory()) {
                                                if (zf.getName().contains("分户")) {
                                                    List<File> wf = new ArrayList<>();
                                                    wf = getSubFiles(zf.getAbsolutePath(), wf);
                                                    uf.put("分层分户图", wf);
                                                } else if (zf.getName().contains("其他")||zf.getName().contains("其它")) {
                                                    List<File> wf = new ArrayList<>();
                                                    wf = getSubFiles(zf.getAbsolutePath(), wf);
                                                    uf.put("其他附件", wf);
                                                } else {
                                                    getFilesTwo(zf.getAbsolutePath(), zddm, unitId, o,status);
                                                }
                                            }
                                        }
                                        o.put(unitId, uf);
                                    } else {
                                        getFilesTwo(tf.getAbsolutePath(), zddm, unitId, o,status);
                                    }
                                }
                            } else if (f.getName().contains("土地") && f.getParent().contains(zddm)) {
                                Map<String, List<File>> uf = new HashMap<>();
                                File mf = new File(f.getAbsolutePath());
                                File[] ds = mf.listFiles();
                                for (File df : ds) {
                                    if (df.isDirectory() && df.getName().contains(zddm)) {
                                        File kf = new File(df.getAbsolutePath());
                                        File[] us = kf.listFiles();
                                        for (File kkf : us) {
                                            if (kkf.isDirectory()) {
                                                if (kkf.getName().contains("地籍调查表")) {
                                                    List<File> wf = new ArrayList<>();
                                                    wf = getSubFiles(kkf.getAbsolutePath(), wf);
                                                    uf.put("地籍调查表", wf);
                                                } else if (kkf.getName().contains("其他")||kkf.getName().contains("其它")) {
                                                    List<File> wf = new ArrayList<>();
                                                    wf = getSubFiles(kkf.getAbsolutePath(), wf);
                                                    uf.put("宗地其他附件", wf);
                                                } else if (kkf.getName().contains("宗地图")) {
                                                    List<File> wf = new ArrayList<>();
                                                    wf = getSubFiles(kkf.getAbsolutePath(), wf);
                                                    uf.put("宗地图", wf);
                                                } else {
                                                    getFilesTwo(df.getAbsolutePath(), zddm, unitId, o,status);
                                                }
                                            }
                                        }
                                        o.put(zddm, uf);
                                    }
                                }
                            } else {
                                getFilesTwo(f.getAbsolutePath(), zddm, unitId, o,status);
                            }
                        }
                    } else {
                        getFilesTwo(fileIndex.getAbsolutePath(), zddm, unitId, o,status);
                    }
                }
            }
        }
        return o;
    }

    public boolean subFileExists(String path,String key){
        File file = new File(path);
        File[] files = file.listFiles();
        for (File fileIndex : files) {
            if (!fileIndex.exists()) {
                throw new NullPointerException("Cannot find " + fileIndex);
            } else if(fileIndex.isDirectory()){
                if(fileIndex.getName().contains(key)){
                   return true;
                }else {
                   if( subFileExists(fileIndex.getAbsolutePath(),key)) return true;
                }
            }
        }
        return false;
    }


    public Map<String,String> getMuLu(String path,Map<String,String> map) {
        File file = new File(path);
        File[] files = file.listFiles();
        if(path.endsWith("扫描档案")){
            for (File fileIndex : files) {
                map.put(fileIndex.getPath().substring(fileIndex.getPath().lastIndexOf("扫描档案")+5),fileIndex.getPath());
            }
            return map;
        }
        if (files != null) {
            for (File fileIndex : files) {
                if (fileIndex.isDirectory()) {
                    if (fileIndex.getParent().contains("扫描档案")) {
                    } else {
                        getMuLu(fileIndex.getAbsolutePath(),map);
                    }
                }
            }
        }
        return map;
    }


    public Map<String,Map<String,List<File>>> getFilesByZddm(String path,String zddm,String unitId,Map<String,Map<String,List<File>>> o,Integer status) {
        File file = new File(path);
        File[] zs = file.listFiles();
        for (File f : zs) {
            if (f.getName().contains(zddm)) {
                File mf = new File(f.getAbsolutePath());
                File[] ms = mf.listFiles();
                for (File tf : ms) {
                    if (tf.getName().contains(unitId)) {
                        //修改材料上传补录标志 补录的时候需要用
                        if(status==4){
                            ruralInfoMapper.updateCommitToBdcByZddm("3",zddm,unitId);
                        }
                        Map<String, List<File>> uf = new HashMap<>();
                        File ff = new File(tf.getAbsolutePath());
                        File[] fs = ff.listFiles();
                        List<File> s = new ArrayList<>();
                        for (File zf : fs) {
                            if (zf.isFile()) {
                                s.add(zf);
                                uf.put("房屋附件", s);
                            } else if (zf.isDirectory()) {
                                if (zf.getName().contains("分户")) {
                                    List<File> wf = new ArrayList<>();
                                    wf = getSubFiles(zf.getAbsolutePath(), wf);
                                    uf.put("分层分户图", wf);
                                } else if (zf.getName().contains("其他")||zf.getName().contains("其它")) {
                                    List<File> wf = new ArrayList<>();
                                    wf = getSubFiles(zf.getAbsolutePath(), wf);
                                    uf.put("其他附件", wf);
                                } else {
                                    getFilesByZddm(zf.getAbsolutePath(), zddm, unitId, o,status);
                                }
                            }
                        }
                        o.put(unitId, uf);
                    } else {
                        getFilesByZddm(tf.getAbsolutePath(), zddm, unitId, o,status);
                    }
                }
            } else if (f.getName().contains("土地") && f.getParent().contains(zddm)) {
                Map<String, List<File>> uf = new HashMap<>();
                File mf = new File(f.getAbsolutePath());
                File[] ds = mf.listFiles();
                for (File df : ds) {
                    if (df.isDirectory() && df.getName().contains(zddm)) {
                        File kf = new File(df.getAbsolutePath());
                        File[] us = kf.listFiles();
                        for (File kkf : us) {
                            if (kkf.isDirectory()) {
                                if (kkf.getName().contains("地籍调查表")) {
                                    List<File> wf = new ArrayList<>();
                                    wf = getSubFiles(kkf.getAbsolutePath(), wf);
                                    uf.put("地籍调查表", wf);
                                } else if (kkf.getName().contains("其他")||kkf.getName().contains("其它")) {
                                    List<File> wf = new ArrayList<>();
                                    wf = getSubFiles(kkf.getAbsolutePath(), wf);
                                    uf.put("宗地其他附件", wf);
                                } else if (kkf.getName().contains("宗地图")) {
                                    List<File> wf = new ArrayList<>();
                                    wf = getSubFiles(kkf.getAbsolutePath(), wf);
                                    uf.put("宗地图", wf);
                                } else {
                                    getFilesByZddm(df.getAbsolutePath(), zddm, unitId, o,status);
                                }
                            }
                        }
                        o.put(zddm, uf);
                    }
                }
            } else {
                getFilesByZddm(f.getAbsolutePath(), zddm, unitId, o,status);
            }
        }
        return o;
    }



}
/**
     * 合并文件并解析附件材料数据
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    @ResponseBody
    @RequestMapping("/caiFileMerge")
    public SimpleJsonResult mergeUploadCaiData(String applicationId, String intoFlag, String fileName, String checkData, HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (StringUtils.isBlank(applicationId)) {
            return failureJsonResult("请先上传属性数据");
        }
        Subject subject = SecurityUtils.getSubject();
        //获取所属机构信息
        SysUser user = (SysUser) subject.getPrincipal();
        long start = System.currentTimeMillis();
        FileOutputStream fileOutputStream = null;
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        RuralInfo ruralInfo = ruralInfoMapper.select(applicationId);
        //合并压缩包
        //获取项目的根路径
        String realpath = request.getSession().getServletContext().getRealPath("/");
        final String Temp_Video_Path = "video/" + fileName;
        String fileNameOut = fileName;
        String classFile = URLDecoder.decode(this.getClass().getClassLoader().getResource("/").getPath(), "utf-8");
        String path = classFile + "../static/fileSpace/" + applicationId + "/" + fileNameOut + "/";//总路径,包括zip文件和解压后的文件
        String newFilePath = path + "fileOut";
        String zipPath = path + "zip/" + fileNameOut + ".zip";
        File video = new File(zipPath);
        try {
            //先判断文件的父目录是否存在,不存在需要创建;否则报错
            if (!video.getParentFile().exists()) {
                video.getParentFile().mkdirs();
                video.createNewFile();//创建文件
            }
            //创建流
            fileOutputStream = new FileOutputStream(video);

            // 转成集合,便于排序
            List<File> fileList = new ArrayList<>();
            fileList = zipUtil.getSubFiles(realpath + Temp_Video_Path + "/", fileList);
            // 从小到大排序
            Collections.sort(fileList, new Comparator<File>() {

                @Override
                public int compare(File o1, File o2) {
                    String name1 = o1.getName();
                    String name2 = o2.getName();
                    if (Integer.parseInt(name1.substring(0, name1.lastIndexOf("."))) < Integer.parseInt(name2.substring(0, name2.lastIndexOf(".")))) {
                        return -1;
                    }
                    return 1;
                }
            });

            // 输出流
            outChannel = fileOutputStream.getChannel();
            // 合并
            for (File f : fileList) {
                inChannel = new FileInputStream(f).getChannel();
                inChannel.transferTo(0, inChannel.size(), outChannel);
                inChannel.close();

                //获取文件上级目录
                File prantFile = f.getParentFile();
                // 删除分片
                f.delete();
                if (prantFile.isDirectory() && prantFile.listFiles().length <= 0) {
                    prantFile.delete();
                }
            }

            // 关闭流
            fileOutputStream.close();
            outChannel.close();
            System.out.println("合并文件成功");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inChannel != null) {
                try {
                    inChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outChannel != null) {
                try {
                    outChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        //解析压缩包
        String mdbFilePath = null;
        try {
            mdbFilePath = zipUtil.unZipFiles(video, newFilePath,"fjcl");//解压文件,获取文件路径
        } catch (Exception e) {
            e.printStackTrace();
            //插入错误日志表
            return failureJsonResult("解压执行失败");
        }
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("applicationId", applicationId);
        //if ("0".equals(intoFlag)) {//覆盖导
        //    //删除附件信息
        //    ruralInfoService.removeUpfile(Long.valueOf(app文件上传ftp失败licationId), null);
        //}
        //获取导入成功的房子的不动产单元号和宗地代码集合
        List<Map<String, String>> hlist = ruralInfoService.getHouseList(applicationId);
        Map<String,String> as = new HashMap<>();
        zipUtil.getMuLu(newFilePath,as);
        String info = "";
        if (hlist != null && hlist.size() > 0) {
            for (Map<String, String> m : hlist) {
                String unitId = m.get("unitid");
                String zddm = m.get("zddm");
                if(!as.containsKey(zddm)){
                    continue;
                }
                try {
                    ruralInfoService.insertFiles(applicationId, as.get(zddm), zddm, unitId);
                } catch (Exception e) {
                    System.out.println("======================================"+e.toString());
                    info+=unitId+" "+e.getMessage();
                    continue;
                }
            }
        } else {
            return failureJsonResult("没有有效的房屋数据导入,请确认");
        }
        //附件材料上传
        ruralInfoService.uploadFile(applicationId,user);
        zipUtil.deleteFiles(path);//删除mdb文件夹
        zipUtil.deleteFiles( path + "zip/" + fileNameOut + "zip");//删除压缩包文件夹
        System.out.println("##################applicationId:"+applicationId+"材料文件上传结束##################");
        if(ruralInfo.getExamineStatus()==4){//材料补录
            //修改同步标志未待同步
            ruralInfoMapper.updateCommitToBdcRural(applicationId,"3");
            System.out.println("##################applicationId:"+applicationId+"材料文件补录开始##################");
            ruralInfoService.imageProcess(applicationId,user);
            System.out.println("##################applicationId:"+applicationId+"材料文件补录结束##################");
            long end = System.currentTimeMillis();
            System.out.println("材料文件补录完成,耗时:" + (end - start) +" ms");
        }
        if(info!=""){
            return failureJsonResult("扫描档案:["+info+"]上传失败,其他附件材料上传成功");
        }
        long end = System.currentTimeMillis();
        System.out.println("附件材料上传成功完成,耗时:" + (end - start) +" ms");
        return successJsonResult("附件材料上传成功");
    }