package com.tofly.base.controller;

import cn.hutool.core.io.FileTypeUtil;
import com.tofly.common.core.entity.ResultRespone;
import com.tofly.common.ftp.config.FtpUtil;
import com.tofly.common.core.util.StringUtil;
import com.tofly.common.core.util.io.IOUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Administrator
 * @date 2019/10/14  17:20
 */
@RestController
@RequestMapping("/file")
@Api(tags="文件FTP相关操作")
@Slf4j
public class CommonFtpController {

    /**
     * 返回图片
     * @param response
     * @return
     */
    @GetMapping(value = "/loadImg")
    @ApiOperation(value = "根据FTP文件地址获取图片")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "remotePath", value = "图片地址", required = true, dataType = "String"),
            @ApiImplicitParam(name = "access_token", value = "token信息", required = true, dataType = "String")
    })
    public byte[] loadFileImg(@RequestParam(value = "remotePath")String remotePath, @RequestParam(value = "access_token")String access_token, HttpServletResponse response){
        //String filename="/xnkd/demo/pic/QQ图片20191014133817.png";
        String fileType=remotePath.substring(remotePath.lastIndexOf("."));
        if (StringUtil.isNotEmpty(fileType)) {
            fileType = fileType.toLowerCase();
        }
        switch (fileType) {
            case ".jpg":
            case ".jpeg":
                response.setContentType(MediaType.IMAGE_JPEG_VALUE);
                break;
            case ".png":
                response.setContentType(MediaType.IMAGE_PNG_VALUE);
                break;
            case ".gif":
                response.setContentType(MediaType.IMAGE_GIF_VALUE);
                break;
            default:
                response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
                break;
        }
        byte[] b= FtpUtil.getByteDataforFile(remotePath);
        return b;
    }

    /**
     * 音频流
     */
    @SneakyThrows
    @GetMapping(value = "/loadAudio")
    @ApiOperation(value = "根据FTP文件地址获取音频")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "remotePath", value = "音频文件地址", required = true, dataType = "String"),
            @ApiImplicitParam(name = "access_token", value = "token信息", required = true, dataType = "String")

    })
    public void wavStream(String remotePath,String access_token,HttpServletRequest request, HttpServletResponse response) {
        //String remotePath = "/xnkd/demo/pic/海阔天空.mp3";

        File music = null;
        music = File.createTempFile("tmp", remotePath.substring(remotePath.lastIndexOf(".")));

        OutputStream ops = new FileOutputStream(music);
        Boolean isSucccess = FtpUtil.retrieveFile(remotePath, ops);
        log.info("=====写入临时文件成功与否：====" + isSucccess);

        if (!music.exists()) {
            log.info("不存在 文件名为：" + remotePath + "的音频文件！");
        }

        String range = request.getHeader("Range");
        //开始下载位置
        long startByte = 0;
        //结束下载位置
        long endByte = music.length() - 1;
        //有range的话
        if (range != null && range.contains("bytes=") && range.contains("-")) {
            range = range.substring(range.lastIndexOf("=") + 1).trim();
            String ranges[] = range.split("-");
            try {
                //判断range的类型
                if (ranges.length == 1) {
                    //类型一：bytes=-2343
                    if (range.startsWith("-")) {
                        endByte = Long.parseLong(ranges[0]);
                    }
                    //类型二：bytes=2343-
                    else if (range.endsWith("-")) {
                        startByte = Long.parseLong(ranges[0]);
                    }
                }
                //类型三：bytes=22-2343
                else if (ranges.length == 2) {
                    startByte = Long.parseLong(ranges[0]);
                    endByte = Long.parseLong(ranges[1]);
                }
            } catch (NumberFormatException e) {
                startByte = 0;
                endByte = music.length() - 1;
            }
        }
        //要下载的长度
        long contentLength = endByte - startByte + 1;
        //文件名
        String fileName = music.getName();
        //文件类型
        String contentType = FileTypeUtil.getType(music);

        //各种响应头设置
        //参考资料：https://www.ibm.com/developerworks/cn/java/joy-down/index.html
        //坑爹地方一：看代码
        response.setHeader("Accept-Ranges", "bytes");
        //坑爹地方二：http状态码要为206
        response.setStatus(206);
        response.setContentType(contentType);
        response.setHeader("Content-Type", contentType);
        //这里文件名换你想要的，inline表示浏览器直接实用（我方便测试用的）
        //参考资料：http://hw1287789687.iteye.com/blog/2188500
        // response.setHeader("Content-Disposition", "inline;filename=test.mp3");
        response.setHeader("Content-Length", String.valueOf(contentLength));
        //坑爹地方三：Content-Range，格式为
        // [要下载的开始位置]-[结束位置]/[文件总大小]
        response.setHeader("Content-Range", "bytes " + startByte + "-" + endByte + "/" + music.length());
        BufferedOutputStream outputStream = null;
        RandomAccessFile randomAccessFile = null;
        //已传送数据大小
        long transmitted = 0;
        try {
            randomAccessFile = new RandomAccessFile(music, "r");
            outputStream = new BufferedOutputStream(response.getOutputStream());
            byte[] buff = new byte[2048];
            int len = 0;
            randomAccessFile.seek(startByte);
            //坑爹地方四：判断是否到了最后不足4096（buff的length）个byte这个逻辑（(transmitted + len) <= contentLength）要放前面！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！
            //不然会会先读取randomAccessFile，造成后面读取位置出错，找了一天才发现问题所在
            while ((transmitted + len) <= contentLength && (len = randomAccessFile.read(buff)) != -1) {
                outputStream.write(buff, 0, len);
                transmitted += len;
                //停一下，方便测试，用的时候删了就行了
            }
            //处理不足buff.length部分
            if (transmitted < contentLength) {
                len = randomAccessFile.read(buff, 0, (int) (contentLength - transmitted));
                outputStream.write(buff, 0, len);
                transmitted += len;
            }
            outputStream.flush();
            response.flushBuffer();
            randomAccessFile.close();
            log.info("下载完毕：" + startByte + "-" + endByte + "：" + transmitted);
        } finally {
            try {
                if (randomAccessFile != null) {
                    randomAccessFile.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 返回图片
     * @param response
     * @return
     */
    @GetMapping(value = "/downloadFile")
    @ApiOperation(value = "根据FTP文件地址下载文件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "remotePath", value = "文件地址", required = true, dataType = "String"),
            @ApiImplicitParam(name = "fileName", value = "文件名称", required = true, dataType = "String")
    })
    @SneakyThrows
    public void downloadFile(String remotePath,String fileName,  HttpServletResponse response,HttpServletRequest request){
        byte[] data = FtpUtil.getByteDataforFile(remotePath);
        response.reset();
        response.setCharacterEncoding("UTF-8");
        String userAgent = request.getHeader("User-Agent");
        String formFileName;
        if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
            // 针对IE或者以IE为内核的浏览器：
            formFileName = URLEncoder.encode(fileName, "UTF-8");
        } else {
            // 非IE浏览器的处理：
            formFileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
        }
        response.setHeader("Content-Disposition", String.format("attachment; filename=%s",formFileName));
        response.addHeader("Content-Length", "" + data.length);
        response.setContentType("application/octet-stream; charset=UTF-8");
        response.setHeader("content-type", "application/octet-stream");
        try{
            IOUtil.write(response.getOutputStream(), Boolean.TRUE, data);
        }catch (IOException e){
            log.error(e.getMessage());
            e.getMessage();
        }
    }

    @GetMapping(value = "/getFileList")
    @ApiOperation(value = "根据FTP文件目录查询文件信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "remotePath", value = "文件目录", required = true, dataType = "String")
    })
    @SneakyThrows
    public ResultRespone getFileList(String remotePath){
        FTPFile[] ftpFiles = FtpUtil.retrieveFTPFiles(remotePath);
        if(ftpFiles==null || ftpFiles.length==0){
            return ResultRespone.failed("该目录未获取到ftp文件");
        }
        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        final DecimalFormat df = new DecimalFormat("0.00");//格式化小数
        List<Map> collect = Arrays.stream(ftpFiles).map(f -> {
            Map map = new HashMap();
            map.put("fileName", f.getName());
            map.put("size", df.format((double)f.getSize()/1024/1024)+"M");

            String dateStr = sdf.format(f.getTimestamp().getTime());
            map.put("createTime", dateStr);
            return map;
        }).collect(Collectors.toList());
        return ResultRespone.success(collect);
    }
}
