package cn.myapps.runtime.common.controller;


import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;

import javax.mail.internet.MimeUtility;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.util.StrUtil;
import cn.myapps.common.controller.Resource;
import cn.myapps.conf.FileModeConfig;
import cn.myapps.util.StringUtil;
import cn.myapps.util.ftp.FtpUtils;
import com.itextpdf.kernel.color.Color;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.*;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.extgstate.PdfExtGState;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.myapps.common.data.ParamsTable;
import cn.myapps.common.util.PropertyUtil;
import cn.myapps.util.FileEncryptAndDecrypt;
import io.swagger.annotations.Api;

/**
 * Download Restful 接口
 *
 * @author ekko
 */
@Api(tags = "下载模块")
@Component
@RequestMapping(path = "/api/runtime", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class DownloadController extends AbstractRuntimeController {
    private static final Logger logger = LoggerFactory.getLogger(DownloadController.class);
    @Autowired
    private HttpServletResponse httpResponse;

    /**
     * 判断文件是否存在
     * @return
     */
    @GetMapping("/file/isFileExisted")
    @ApiOperation(value = "校验文件", notes = "校验文件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "filename",value = "文件名",required = true,paramType = "query",dataType = "string"),
            @ApiImplicitParam(name = "filepath",value = "文件相对路径",required = true,paramType = "query",dataType = "string")
    })
    public Resource isFileExisted(){
        ParamsTable params = this.getParams();
        HttpServletResponse response = httpResponse;
        String encoding = "ISO-8859-1";
        String filename = params.getParameterAsString("filename");
        String filepath = params.getParameterAsString("filepath");
        if (!filepath.startsWith("/uploads/")) {
            return new Resource(500,"文件类型不合法！",null);
        }
        try {
            filepath = URLDecoder.decode(filepath, encoding);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return new Resource(500,"编码类型错误！",null);
        }
        String realPath = PropertyUtil.getPath();
        String realFilePath = realPath + filepath;
        if (FileEncryptAndDecrypt.isEncrypt(realFilePath)) {
            //解密下载
            realFilePath = FileEncryptAndDecrypt.encrypt(realFilePath);
        }
        File file = new File(realFilePath);

        if (!file.exists()) {
            return new Resource(500,"文件不存在！",null);
        }
        return new Resource(200,"文件存在！",null);
    }

    /**
     * 文件下载
     * @return
     */
    @RequestMapping("/file/download")
    @ApiOperation(value = "文件下载", notes = "文件下载")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "filename",value = "文件名",required = true,paramType = "query",dataType = "string"),
            @ApiImplicitParam(name = "filepath",value = "文件相对路径",required = true,paramType = "query",dataType = "string"),
            @ApiImplicitParam(name = "watermarkStr",value = "水印名",required = true,paramType = "query",dataType = "string")
    })
    public void doFileDownload(){
        OutputStream os = null;
        BufferedInputStream reader = null;
        try {
            File tempFile = null;
            boolean isTemp = false;
            ParamsTable params = this.getParams();
            HttpServletResponse response = httpResponse;
            String encoding = "ISO-8859-1";
            String filename = params.getParameterAsString("filename");
            String filepath = params.getParameterAsString("filepath");
            String watermarkStr = params.getParameterAsString("watermarkStr");
            if(!filepath.startsWith("/uploads/")){
                response.getWriter().print("Error: file illegal!");
            }

            filepath = URLDecoder.decode(filepath, encoding);

            String realPath = PropertyUtil.getPath();
            String realFilePath = realPath + filepath;

            if (FileModeConfig.getUseFtp() && filepath.indexOf("/uploads/lib/icon/") <0 && filepath.indexOf("/uploads/temp/") <0) {
                try {
                    //文件路径
                    String filePath = filepath.substring(0, filepath.lastIndexOf("/") + 1);
                    //文件名称
                    String fileName = filepath.substring(filepath.lastIndexOf("/") + 1);

                    String tempPath = PropertyUtil.getPath() + "/uploads/temp/";
                    tempFile = FtpUtils.downloadFile(FileModeConfig.getHost(),
                            FileModeConfig.getUserName(),
                            FileModeConfig.getPassword(),
                            FileModeConfig.getPort(),
                            (StrUtil.isEmpty(FileModeConfig.getFilePath()) ? "" : FileModeConfig.getFilePath()) + filePath,
                            tempPath,
                            fileName);
                    realFilePath = tempFile.getPath();
                } catch (Exception e) {
                    logger.error("调用FTP文件异常:{}", filepath, e);
                }
            }

            realFilePath = realFilePath.replaceAll("\\\\", "/").replace("\\","/");
            if (!StringUtil.isBlank(watermarkStr)){
                String pdfRealPath = generatedWatermarkPdf(realFilePath,watermarkStr);
                if (pdfRealPath!=null){
                    isTemp = true;
                    realFilePath = pdfRealPath;
                    String fileNameWithoutType = filename.substring(0,filename.indexOf("."));
                    filename = fileNameWithoutType + ".pdf";
                }
            }
            if(FileEncryptAndDecrypt.isEncrypt(realFilePath)){
                //解密下载
                realFilePath = FileEncryptAndDecrypt.encrypt(realFilePath);
            }

            File file = new File(realFilePath);

            if(!file.exists()){
                response.getWriter().print("找不到指定文件");
                response.getWriter().close();
            }

            String agent = request.getHeader("USER-AGENT");

//            response.setContentType("application/octet-stream;charset=ISO-8859-1");
            response.setContentType("application/force-download");// 设置强制下载不打开
            if(null != agent){
                if(-1 != agent.indexOf("Firefox")) {
                    response.setHeader("Content-Disposition", "attachment;filename=\"" + MimeUtility.encodeText(filename, encoding, "B") + "\"");
                } else if(-1 != agent.indexOf("Trident") || -1 != agent.indexOf("MSIE")) {
                    filename = URLEncoder.encode(filename,"UTF8");
                    response.setHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
                }else if(agent.toUpperCase().indexOf("EDGE")>0){
                    response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(filename,"UTF-8"));
                }else{
                    response.setHeader("Content-Disposition", "attachment;filename=\"" + new String(filename.getBytes("UTF-8"),"iso-8859-1") + "\"");
                }
            } else {
                response.setHeader("Content-Disposition", "attachment;filename=\"" + new String(filename.getBytes("UTF-8"),"iso-8859-1") + "\"");
            }
            os = response.getOutputStream();

            reader = new BufferedInputStream(new FileInputStream(file));
            IOUtils.copy(reader, os);
            tempFile.deleteOnExit();
            if(isTemp){
                file.deleteOnExit();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try{
                if (os != null) {
                    reader.close();
                }
                if ( reader != null) {
                    reader.close();
                }
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
    private String generatedWatermarkPdf( String realFilePath, String waterMarkStr) throws Exception {
        String file = realFilePath.substring(realFilePath.lastIndexOf("/"),realFilePath.length());
        String fileName = file.substring(1,file.lastIndexOf("."));
        //PDF文件名
        String pdfFileName = "/swf/" + fileName + ".pdf";
        //

        //获取PDF文件全路径
        String pdfFilePath = realFilePath.replace(file, pdfFileName);

        if (!new File(pdfFilePath).exists()) {
            return null;
        }

        File pdfFile = new File(pdfFilePath);
        File pdfFileWithWaterMark = null;

        String swfPath = pdfFilePath.substring(0, pdfFilePath.lastIndexOf("/")) + File.separator + "watermark" + File.separator;
        File saveFile = new File(swfPath);
        if (!saveFile.exists()) {
            saveFile.mkdirs();
        }

        String pdfNameWithWaterMark = fileName + ".pdf";
        String pdfPathWithWaterMark = null;
        pdfPathWithWaterMark = swfPath + pdfNameWithWaterMark;
        pdfFileWithWaterMark = new File(pdfPathWithWaterMark);

        if (pdfFileWithWaterMark.exists()){
            return pdfPathWithWaterMark;
        }


        ByteArrayOutputStream baos = null;

        baos = new ByteArrayOutputStream();

        // 设置只读只允许打印
        WriterProperties props = new WriterProperties().setStandardEncryption(null, null, EncryptionConstants.ALLOW_PRINTING,
                EncryptionConstants.ENCRYPTION_AES_128 | EncryptionConstants.DO_NOT_ENCRYPT_METADATA);

        // 未加水印的源文件
        PdfReader reader = new PdfReader(pdfFilePath);
        // 加完水印的输出文件
        PdfWriter writer = new PdfWriter(baos, props);
        PdfDocument pdfDoc = new PdfDocument(reader, writer);
        com.itextpdf.layout.Document doc = new com.itextpdf.layout.Document(pdfDoc);
        // 文字水印
        Paragraph p = null;
        if (!StringUtil.isBlank(waterMarkStr)) {
            PdfFont font = null;
            font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", false);
            p = new Paragraph(waterMarkStr).setFont(font).setFontSize(30).setFontColor(Color.GRAY).setOpacity(new Float(0.4));
        }
        // 文档页数
        int n = pdfDoc.getNumberOfPages();
        // transparency
        PdfExtGState gs1 = new PdfExtGState();
        // gs1.setFillOpacity(0.5f);
        // properties
        PdfCanvas over;
        Rectangle pagesize;
        float x, y;
        // loop over every page
        // loop over every page
        for (int i = 1; i <= n; i++) {
            PdfPage pdfPage = pdfDoc.getPage(i);
            pagesize = pdfPage.getPageSizeWithRotation();
            pdfPage.setIgnorePageRotationForContent(true);
            //加载位置 3行2列逻辑
            int xCount = 3;
            int yCount = 4;
            x = (pagesize.getLeft() + pagesize.getRight());
            y = (pagesize.getTop() + pagesize.getBottom());
            int line = (int) y / yCount;
            int cloumn = (int) x / xCount;
            for (int lineTemp = 1; lineTemp < yCount; lineTemp++) {
                for (int cloumnTemp = 1; cloumnTemp < xCount; cloumnTemp++) {
                    addWatermarkPlace(doc, p, gs1, pagesize, i, pdfPage, cloumn * cloumnTemp, line * lineTemp);
                }
            }
//               addWatermarkPlace(doc, p, gs1, pagesize, i, pdfPage, xAxie, yAxie);
        }
        doc.close();

        FileOutputStream fos2 = new FileOutputStream(pdfFileWithWaterMark);
        if (baos != null) {
            baos.writeTo(fos2);
            baos.flush();
            baos.close();
            fos2.flush();
            fos2.close();
        }
        return pdfPathWithWaterMark;
    }

    private void addWatermarkPlace(Document doc, Paragraph p, PdfExtGState gs1, Rectangle pagesize, int i, PdfPage pdfPage, int xAxie, int yAxie) {
        float x;
        float y;
        PdfCanvas over;
        x = xAxie;
        y = yAxie;
        over = new PdfCanvas(pdfPage.newContentStreamBefore(), pdfPage.getResources(), pdfPage.getDocument());
        over.saveState();
        over.setExtGState(gs1);
        // 文字水印
        if (p != null) {
            doc.showTextAligned(p, x, y, i, TextAlignment.CENTER, VerticalAlignment.TOP, 0.3f);
        }
        over.restoreState();
    }
}
