package org.jeecg.modules.ctop.controller;

import cn.com.ctop.common.module.utils.Check;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Slf4j
@RestController
@RequestMapping("/download")
public class ImageDownloadController {
    @RequestMapping(value = "/zip")
    @ResponseBody
    public void downloadFiles(HttpServletRequest request, HttpServletResponse response, @RequestBody JSONObject json) {
        log.info("封面文件开始压缩下载");
        long l = System.currentTimeMillis();

        // 响应头的设置
        response.reset();
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");

        // 设置压缩包的名字
        // 解决不同浏览器压缩包名字含有中文时乱码的问题
        String downloadName = System.currentTimeMillis() + ".zip";
        String agent = request.getHeader("USER-AGENT");
        try {
            if (agent.contains("MSIE") || agent.contains("Trident")) {
                downloadName = java.net.URLEncoder.encode(downloadName, StandardCharsets.UTF_8.toString());
            } else {
                downloadName = new String(downloadName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        response.setHeader("Content-Disposition", "attachment;fileName=\"" + downloadName + "\"");

        // 设置压缩流：直接写入response，实现边压缩边下载
        ZipOutputStream zipos = null;
        try {
            zipos = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
            zipos.setMethod(ZipOutputStream.DEFLATED); // 设置压缩方法
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 循环将文件写入压缩流
        DataOutputStream os = null;
        JSONArray urls = json.getJSONArray("urls");
        if (Check.isNull(urls)) {
            return;

        }

        for (int i = 0; i < urls.size(); i++) {
            String url = urls.getString(i);
            String fileName = getFileTypeByUrl(url);
            File file = getFileByUrl(url, fileName);
            try {
                // 添加ZipEntry，并ZipEntry中写入文件流
                // 这里，加上i是防止要下载的文件有重名的导致下载失败
                zipos.putNextEntry(new ZipEntry(fileName));
                os = new DataOutputStream(zipos);
                InputStream is = new FileInputStream(file);
                byte[] b = new byte[100];
                int length = 0;
                while ((length = is.read(b)) != -1) {
                    os.write(b, 0, length);
                }
                is.close();
                zipos.closeEntry();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        log.info("封面文件压缩下载完成,功耗时:{} ms", System.currentTimeMillis() - l);

        // 关闭流
        try {
            os.flush();
            os.close();
            zipos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    //url转file
    private File getFileByUrl(String fileUrl, String suffix) {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        BufferedOutputStream stream = null;
        InputStream inputStream = null;
        File file = null;
        try {
            URL imageUrl = new URL(fileUrl);
            HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            inputStream = conn.getInputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(buffer)) != -1) {
                outStream.write(buffer, 0, len);
            }
            file = File.createTempFile("file", suffix);
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            stream = new BufferedOutputStream(fileOutputStream);
            stream.write(outStream.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null){
                    inputStream.close();
                }
                if (stream != null){
                    stream.close();
                }
                outStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    //根据获取文件后缀
    private String getFileTypeByUrl(String url) {

        String suffixes = "3fr|arw|bmp|cr2|crw|dcr|dng|eps|erf|gif|icns|ico|jpeg|jpg|mos|mrw|nef|odd|orf|pdf|pef|png|ppm|ps|psd|raf|raw|svg|svgz|tif|tiff|webp|x3f|xcf|xps|		7z|ace|alz|arc|arj|bz|bz2|cab|cpio|deb|dmg|eml|gz|img|iso|jar|lha|lz|lzma|lzo|rar|rpm|rz|tar|tar.7z|tar.bz|tar.bz2|tar.gz|tar.lzo|tar.xz|tar.Z|tbz|tbz2|tgz|tZ|tzo|xz|z|zip|aac|ac3|aif|aifc|aiff|amr|caf|flac|m4a|m4b|mp3|oga|ogg|sf2|sfark|voc|wav|weba|wma|		3g2|3gp|3gpp|avi|cavs|dv|dvr|flv|gif|m2ts|m4v|mkv|mod|mov|mp4|mpeg|mpg|mts|mxf|ogg|rm|rmvb|swf|ts|vob|webm|wmv|wtv|		abw|djvu|doc|docm|docx|html|lwp|md|odt|pages|pages.zip|pdf|rst|rtf|sdw|tex|txt|wpd|wps|zabw|eps|html|key|key.zip|odp|pdf|pps|ppsx|ppt|pptm|pptx|ps|sda|swf|		csv|html|numbers|numbers.zip|ods|pdf|sdc|xls|xlsm|xlsx|azw|azw3|azw4|cbc|cbr|cbz|chm|docx|epub|fb2|htm|html|htmlz|lit|lrf|mobi|odt|oeb|pdb|pdf|pml|prc|rb|rtf|snb|tcr|txt|txtz|eot|otf|ttf|woff|dwg|dxf|ai|cdr|cgm|emf|eps|pdf|ps|sk|sk1|svg|svgz|vsd|wmf|website";
        Pattern pat = Pattern.compile("[\\w]+[\\.](" + suffixes + ")");// 正则判断
        Matcher mc = pat.matcher(url);// 条件匹配
        String substring = "";
        while (mc.find()) {
            substring = mc.group();// 截取文件名后缀名
        }
        return substring;

    }
}
