package com.xkrs.utils;

import cn.hutool.core.io.resource.InputStreamResource;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.tus.java.client.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Objects;

/**
 * @author dong
 * @date 2020/12/31
 */
@Component
public class FileFastDfs {

    @Value("${dfs.ip}")
    public String ip;
    @Value("${dfs.port}")
    public String port;

//    @Value("${dfs.upload}")
//    public String upload;
//
//    @Value("${dfs.delete}")
//    public String delete;

    @Resource
    private KafkaTemplate<String, Object> kafkaTemplate;
    private static final Logger log = LoggerFactory.getLogger(FileFastDfs.class);
    private static final String STATUS = "status";
    private static final String UPLOAD_BIG_PATH = "http://192.168.2.166:2001/group1/big/upload";
    private static final String UPLOAD_PATH = "http://192.168.2.166:2001/group1/upload";

    /**
     * 文件上传到dfs服务器
     * @param file
     * @param dir
     * @return
     */
    public String uploadFile(MultipartFile file, String dir) {
        File file1 = null;
        InputStreamResource isr = null;
        try {
            file1 = multipartFileToFile(file);
            isr=new InputStreamResource(file.getInputStream(),
                    file.getOriginalFilename());
        } catch (IOException e) {
            log.info("IO错误{}", (Object) e.getStackTrace());
        } catch (Exception e) {
            e.printStackTrace();
        }
        //文件地址
        //声明参数集合
        HashMap<String, Object> paramMap = new HashMap<>(7);
        //文件
        paramMap.put("file", isr);
        //输出
        paramMap.put("output", "json");
        //自定义路径
        paramMap.put("path", dir);
        //场景  文件分类
        if (null == file1) {
            return null;
        }
        String name = file1.getName();
        System.err.println("file:" + file1.getName());
        paramMap.put("scene", name.substring(name.lastIndexOf(".") + 1));
        paramMap.put("fileName", System.currentTimeMillis() + ""
                + Objects.requireNonNull(file.getOriginalFilename())
                        .substring(file.getOriginalFilename().lastIndexOf(".")));
        System.err.println(paramMap);
        //
        String result = HttpUtil.post("http://" + ip + ":" + port + "/group1/upload", paramMap);
        System.err.println(result);

        // 拿出状态码，判断上传状态
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = null;
        try {
            node = mapper.readTree(result);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        final String fail = "fail";
        if (null != node) {
            if (fail.equals(node.path(STATUS).asText())) {
                return null;
            }
        }
        return result;
    }

    /**
     * @description: 文件上传到dfs服务器
     * @params  [file：File 文件, dir 文件存放路径]
     * @author: wd
     * @time: 2020/3/31 2020/3/31
     */
    public String uploadFile(File file, String dir) {
        //文件地址
        //声明参数集合
        HashMap<String, Object> paramMap = new HashMap<>(7);
        //文件
        paramMap.put("file", file);
        //输出
        paramMap.put("output", "json");
        //自定义路径
        paramMap.put("path", dir);
        //场景
//        System.err.println(file.getName());

        // paramMap.put("fileName", System.currentTimeMillis() + "" + file.getName().substring(file.getName().lastIndexOf(".")));
        paramMap.put("fileName", file.getName());
        System.err.println(paramMap);
        //上传
        String result = HttpUtil.post("http://" + ip + ":" + port + "/group1/upload", paramMap);
        System.err.println(result);
        // 拿出状态码，判断上传状态
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = null;
        try {
            node = mapper.readTree(result);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        final String status = "status";
        final String statusFail = "fail";
        if (null != node) {
            if (statusFail.equals(node.path(status).asText())) {
                return null;
            }
        }
        return result;
    }

    /**
     * @description: 文件上传到dfs服务器
     * @params  [file：File 文件, dir 文件存放路径]
     * @author: wd
     * @time: 2020/3/31 2020/3/31
     */
    public String uploadFile(File file, String dir, String fileType) {
        //文件地址
        //声明参数集合
        HashMap<String, Object> paramMap = new HashMap<>(7);
        //文件
        paramMap.put("file", file);
        //输出
        paramMap.put("output", "json");
        //自定义路径
        paramMap.put("path", dir);
        //场景
        System.err.println(file.getName());

        // paramMap.put("fileName", System.currentTimeMillis() + "" + file.getName().substring(file.getName().lastIndexOf(".")));
        paramMap.put("fileName", file.getName());
        paramMap.put("scene", fileType);
        System.err.println(paramMap);
        //上传
        String result = HttpUtil.post("http://" + ip + ":" + port + "/group1/upload", paramMap);
        System.err.println(result);
        // 拿出状态码，判断上传状态
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = null;
        try {
            node = mapper.readTree(result);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        final String status = "status";
        final String statusFail = "fail";
        if (null != node) {
            if (statusFail.equals(node.path(status).asText())) {
                return null;
            }
        }
        return result;
    }

    public String uploadBigFile(File file, String dir, String fileType) {
        // 下面这个一定要注意，如果不设置为true，将会直接返回301
        System.setProperty("http.strictPostRedirect", Boolean.toString(true));
        TusClient tusClient = new TusClient();
        try {
            tusClient.setUploadCreationURL(new URL(UPLOAD_BIG_PATH));

//        tusClient.enableResuming(new TusRedisUrlStrore());
            tusClient.enableResuming(new TusURLMemoryStore());

            final TusUpload upload = new TusUpload(file);
            System.out.println("start upload......");
            TusExecutor executor = new TusExecutor() {
                @Override
                protected void makeAttempt() throws ProtocolException, IOException {
                    TusUploader uploader = tusClient.resumeOrCreateUpload(upload);
                    uploader.setChunkSize(1024 * 1024);

                    long start = System.currentTimeMillis();
                    do {
                        long totalBytes = upload.getSize();
                        long bytesUploaded = uploader.getOffset();
                        double progress = (double) bytesUploaded / totalBytes * 100;

                        System.out.printf("Upload at %06.2f%%.\n", progress);
                    } while (uploader.uploadChunk() > -1);

                    uploader.finish();

                    String uploadUrl = uploader.getUploadURL().toString();
                    System.out.println("Upload finished.");
                    System.out.format("Upload available at: %s\n", uploadUrl);

                    long end = System.currentTimeMillis();

                    System.out.println((end - start) + "ms");
                    // 使用hutool进行秒传置换url
                    String fileId = StrUtil.subAfter(uploadUrl, UPLOAD_BIG_PATH + "/", true);
                    System.out.println("fileId: " + fileId);
                    String url = StrUtil.format("{}?md5={}&output=json", UPLOAD_PATH, fileId);
                    System.out.println("url: " + url);
                    // 上传大文件的时候（1.xG）需要sleep一下，要不然会有问题
                    ThreadUtil.sleep(5000);
                    String result = HttpUtil.get(url);
                }
            };
            executor.makeAttempts();
        } catch (IOException | ProtocolException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @description: 文件base64流获取
     * @params  [fileName ： 文件路径]
     * @return: java.lang.String
     * @author: chqf
     * @time: 2020/3/31 2020/3/31
     */
    public String  getBase64(String fileName) {
        if (fileName == null || "".equals(fileName)) {
            return null;
        }
        InputStream fis = null;
        URL url = null;
        try {
            url = new URL("http://" + ip + ":" + port + "/" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
            System.err.println(url);
            fis = url.openStream();
        } catch (IOException e) {
            log.info("IO错误{}", (Object) e.getStackTrace());
        }
        final ByteArrayOutputStream data = new ByteArrayOutputStream();
        String imgStr = "";
        try {
            if (fis == null) {
                return null;
            }
            int len = -1;
            byte[] buf = new byte[2048];
            while (-1 != (len = fis.read(buf, 0, buf.length))) {
                data.write(buf, 0, len);
            }
            Base64.Encoder encoder = Base64.getEncoder();
            imgStr = encoder.encodeToString(data.toByteArray());
        } catch (IOException e) {
            log.info("IO错误{}", (Object) e.getStackTrace());
        }finally {
            try {
                if (null != fis) {
                    fis.close();
                }
                data.close();
            } catch (IOException e) {
                log.info("IO错误{}", (Object) e.getStackTrace());
            }
        }

        return "data:image/jpeg;base64," + imgStr;
    }

    /**
     * @description: 文件格式转换multipartFil 转为 File 格式
     * @params  [file]
     * @return: java.io.File
     * @author: dong
     * @time: 2020/3/31 2020/3/31
     */
    public File multipartFileToFile(MultipartFile file) throws Exception {

        File toFile = null;
        if ("".equals(file) || file.getSize() <= 0) {
            file = null;
        } else {
            InputStream ins;
            ins = file.getInputStream();
            toFile = new File(Objects.requireNonNull(file.getOriginalFilename()));
            inputStreamToFile(ins, toFile);
            ins.close();
        }
        return toFile;
    }

    private static void inputStreamToFile(InputStream ins, File file) {
        OutputStream os = null;
        try {
            os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            log.info("IO错误{}", (Object) e.getStackTrace());
        }finally {
            try {
                if (null != os) {
                    os.close();
                }
                if (null != ins) {
                    ins.close();
                }
            } catch (IOException e) {
                log.info("IO错误{}", (Object) e.getStackTrace());
            }
        }
    }

    /**
     * @description: 文件base64流获取
     * @params  [fileName ： 文件路径]
     * @return: java.lang.String
     * @author: dong
     * @time: 2020/3/31 2020/3/31
     */
    public Boolean getFile(String fileName, HttpServletResponse response) {
        if (fileName == null || "".equals(fileName)) {
            return null;
        }
        InputStream fis = null;
        URL url = null;
        try {
            url = new URL("http://" + ip + ":" + port + "/" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
            System.err.println(url);
            fis = url.openStream();
            response.reset();
            response.setContentType("bin");
            response.addHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
        } catch (IOException e) {
            log.info("IO错误{}", (Object) e.getStackTrace());
        }
        //
        byte[] b = new byte[256];
        int len;
        try {
            assert fis != null;
            while ((len = fis.read(b)) > 0){
                response.getOutputStream().write(b, 0, len);
            }
        } catch (IOException e) {
            log.info("IO错误{}", (Object) e.getStackTrace());
        }finally {
            try {
                if (null != fis) {
                    fis.close();
                }
            } catch (IOException e) {
                log.info("IO错误{}", (Object) e.getStackTrace());
            }
        }
        return true;
    }

    /**
     * 删除文件 path
     * @param filePath 文件路径 上传返回的path
     * @return
     */
    public Boolean deleteFileByPath(String filePath) {
        if (filePath == null || "".equals(filePath)) {
            return false;
        }
        HashMap<String, Object> paramMap = new HashMap<>(1);
        // 参数
        paramMap.put("path", filePath);

        String result = HttpUtil.post("http://" + ip + ":" + port + "/group1/delete", paramMap);
        System.out.println(result);
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = null;
        try {
            node = mapper.readTree(result);
        } catch (JsonProcessingException e) {

            e.printStackTrace();
        }

        final String statusOk = "ok";

        if (null == node) {
            log.error("返回结果为空");
            return false;
        }
        if (!statusOk.equals(node.path(STATUS).asText())) {
            log.error("未删除成功");
            return false;
        }
        return true;
    }

    /**
     * 删除文件 path
     * @param md5 上传返回的md5
     * @return
     */
    public Boolean deleteFileByMd5(String md5) {
        if (md5 == null || "".equals(md5)) {
            return false;
        }
        HashMap<String, Object> paramMap = new HashMap<>(1);
        // 参数
        paramMap.put("md5", md5);

        String result = HttpUtil.post("http://" + ip + ":" + port + "/group1/delete", paramMap);

        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = null;
        try {
            node = mapper.readTree(result);
        } catch (JsonProcessingException e) {

            e.printStackTrace();
        }
        final String status = "status";
        final String statusOk = "ok";

        if (null == node) {
            log.error("返回结果为空");
            return false;
        }
        if (!statusOk.equals(node.path(status).asText())) {
            log.error("未删除成功");
            return false;
        }
        return true;
    }





    public static void main(String[] args) {
        File file = new File("C:\\Users\\dong\\Desktop\\遥感影像\\遥感影像\\GF1\\GF1_PMS1_E116.8_N36.6_20190528_L1A0004026837-MSS1_ORTHO_MS.tif");
        FileFastDfs fileFastDfs = new FileFastDfs();
    }
}


