package com.crm.rely.backend.util;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * Created by max on 2019/12/12.
 */
public class ExportUtil {


    public static <T extends BaseRowModel> void transferToResponse(String fileName, List<T> t, Class<T> clazz, HttpServletResponse response) throws Exception {

        setResponse(fileName, response);

        OutputStream outputStream = response.getOutputStream();

        outputStream(outputStream, t, clazz);
    }

    public static <T extends BaseRowModel> void transferListToResponse(String fileName, List<List<T>> t,  List<String> sheetNameList,  Class<T> clazz, HttpServletResponse response) throws Exception {

        setResponse(fileName, response);

        OutputStream outputStream = response.getOutputStream();

        outputListStream(outputStream, t, clazz, sheetNameList);
    }

    public static <T extends BaseRowModel> void transferToFile(String path, String fileName, List<T> t, Class<T> clazz) throws Exception {

        String fileFullPath = path + File.separator + fileName;
        FileOutputStream fos = new FileOutputStream(new File(fileFullPath));
        ExcelWriter excelWriter = new ExcelWriter(fos, ExcelTypeEnum.XLSX);
        Sheet sheet = new Sheet(1, 0, clazz);
        excelWriter.write(t, sheet);

        excelWriter.finish();
        if (fos != null) {
            fos.close();
        }

    }

    public static <T extends BaseRowModel> void transferToFile(String path, String fileName, String sheetName, List<T> t, Class<T> clazz) throws Exception {
        String fileFullPath = path + File.separator + fileName;
        FileOutputStream fos = new FileOutputStream(new File(fileFullPath));
        ExcelWriter excelWriter = new ExcelWriter(fos, ExcelTypeEnum.XLSX);
        Sheet sheet = new Sheet(1, 0, clazz);
        sheet.setSheetName(sheetName);
        excelWriter.write(t, sheet);

        excelWriter.finish();
        if (fos != null) {
            fos.close();
        }
    }

    public static <T extends BaseRowModel> void transferToFile(String path, String fileName, List<String> sheetNameList, List<List<T>> t, Class<T> clazz) throws Exception {
        String fileFullPath = path + File.separator + fileName;
        FileOutputStream fos = new FileOutputStream(new File(fileFullPath));
        ExcelWriter excelWriter = new ExcelWriter(fos, ExcelTypeEnum.XLSX);

        for (int i = 0; i < t.size(); i++) {
            List<T> list = t.get(i);
            Sheet sheet = new Sheet(i+1, 0, clazz);
            sheet.setSheetName(sheetNameList.get(i));
            excelWriter.write(list, sheet);
        }

        excelWriter.finish();
        if (fos != null) {
            fos.close();
        }
    }

    public static <T extends BaseRowModel> void transferToExcelResponse(String fileNamePrefix, List<T> t, Class<T> clazz, HttpServletResponse response) throws Exception {
        transferToResponse(genFileName(fileNamePrefix), t, clazz, response);
    }

    public static <T extends BaseRowModel> byte[] getDataToByte(List<T> t, Class<T> clazz) {

        ByteArrayOutputStream os = new ByteArrayOutputStream();

        outputStream(os, t, clazz);

        return os.toByteArray();
    }

    public static void transferToResponse(String fileName, byte[] data, HttpServletResponse response) throws Exception {

        setResponse(fileName, response);

        OutputStream outputStream = response.getOutputStream();

        try {
            outputStream.write(data);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void transferToResponse(String fileName, String absolutePath, HttpServletResponse response) throws Exception {

        setResponse(fileName, response);

        OutputStream outputStream = response.getOutputStream();
        String filePath = absolutePath + File.separator + fileName;
        try (FileInputStream fileInputStream = new FileInputStream(filePath)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = fileInputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 设置response 导出文件的格式和文件名称
     *
     * @param fileName
     * @param response
     * @throws Exception
     */
    private static void setResponse(String fileName, HttpServletResponse response) throws Exception {
        response.setContentType("application/force-download");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));

    }

    /**
     * 吧T数据转化为excel 并把数据写到outputStream流中
     *
     * @param outputStream
     * @param t
     * @param clazz
     * @param <T>
     */
    private static <T extends BaseRowModel> void outputStream(OutputStream outputStream, List<T> t, Class<T> clazz) {
        try {
            ExcelWriter excelWriter = new ExcelWriter(outputStream, ExcelTypeEnum.XLSX);
            Sheet sheet = new Sheet(1, 0, clazz);
            excelWriter.write(t, sheet);
            excelWriter.finish();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 吧T数据转化为excel 并把数据写到outputStream流中
     *
     * @param outputStream
     * @param t
     * @param clazz
     * @param <T>
     */
    private static <T extends BaseRowModel> void outputListStream(OutputStream outputStream, List<List<T>> t, Class<T> clazz, List<String> sheetNameList) {
        try {
            ExcelWriter excelWriter = new ExcelWriter(outputStream, ExcelTypeEnum.XLSX);

            for (int i = 0; i < t.size(); i++) {
                List<T> list = t.get(i);
                Sheet sheet = new Sheet(i+1, 0, clazz);
                sheet.setSheetName(sheetNameList.get(i));
                excelWriter.write(list, sheet);
            }
            excelWriter.finish();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static String genFileName(String fileNamePrefix) {
        StringBuffer stringBuffer = new StringBuffer();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        stringBuffer.append(fileNamePrefix);
        stringBuffer.append("_");
        stringBuffer.append(sdf.format(new Date()));
        stringBuffer.append(".xlsx");
        String fileName = stringBuffer.toString();
        return fileName;
    }
}
