package com.yanzuoguang.cloud.helper;

import com.yanzuoguang.cloud.vo.WebFileVo;
import com.yanzuoguang.util.contants.SystemContants;
import com.yanzuoguang.util.helper.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 上传文件,下载文件操作类
 *
 * @author 颜佐光
 */
public final class WebFileHelper {

    private static final Logger logger = LoggerFactory.getLogger(WebFileHelper.class);

    private static final String CACHE_CONTROL_VALUE = "no-cache, no-store, must-revalidate";

    private static final String CONTENT_DISPOSITION_VALUE = "attachment; filename=\"%s\"";

    private static final String PRAGMA_VALUE = "no-cache";

    private static final String EXPIRES_VALUE = "0";

    private static final String SEPARATE_SPOT = ".";

    private static final String SEPARATE_HR = "-";

    private static final String UTF_8 = "UTF-8";

    private static WebFileVo webFileVo;

    private WebFileHelper() {
        super();
    }

    /**
     * 检查并创建文件夹
     *
     * @param path
     */
    public static boolean createDirectory(String path) {
        File file = new File(path);
        if (!file.isDirectory()) {
            return file.mkdirs();
        }
        return false;
    }

    /**
     * 下载文件,下载文件名为服务器保存文件名
     *
     * @param path 文件路径
     * @return
     */
    public static ResponseEntity download(String path) {
        try {
            FileSystemResource file = new FileSystemResource(path);

            HttpHeaders httpHeaders = buildHttpHeaders(file.getFilename());

            return buildResponseEntity(httpHeaders, file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 下载文件,指定下载文件后文件名
     *
     * @param path 下载路径
     * @param name 重命名
     * @return
     */
    public static ResponseEntity download(String path, String name) {
        try {
            FileSystemResource file = new FileSystemResource(path);

            HttpHeaders httpHeaders = buildHttpHeaders(name);

            return buildResponseEntity(httpHeaders, file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 设置下载headers
     *
     * @param name
     * @return
     */
    private static HttpHeaders buildHttpHeaders(String name) throws UnsupportedEncodingException {
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CACHE_CONTROL, CACHE_CONTROL_VALUE);
        String encodeName = URLEncoder.encode(name, UTF_8);

        if (logger.isDebugEnabled()) {
            logger.debug("download taskDefinition name, and before encode taskDefinition name [{}], and after taskDefinition name[{}]", name, encodeName);
        }

        headers.add(HttpHeaders.CONTENT_DISPOSITION, String.format(CONTENT_DISPOSITION_VALUE, encodeName));
        headers.add(HttpHeaders.PRAGMA, PRAGMA_VALUE);
        headers.add(HttpHeaders.EXPIRES, EXPIRES_VALUE);
        return headers;
    }

    /**
     * 下载设置返回值
     *
     * @param httpHeaders
     * @param file
     * @return
     * @throws IOException
     */
    private static ResponseEntity buildResponseEntity(HttpHeaders httpHeaders, FileSystemResource file) throws IOException {
        return ResponseEntity
                .ok()
                .headers(httpHeaders)
                .contentLength(file.contentLength())
                .contentType(MediaType.parseMediaType(MediaType.APPLICATION_OCTET_STREAM_VALUE))
                .body(new InputStreamResource(file.getInputStream()));
    }


    /**
     * 单文件上传
     *
     * @param multipartFile
     * @param savePath
     * @return
     */
    public static WebFileVo upload(MultipartFile multipartFile, String savePath) {
        String fileName = multipartFile.getOriginalFilename();

        if (!savePath.endsWith(SystemContants.SLASH) || !savePath.endsWith(SystemContants.UNSLASH)) {
            savePath += SystemContants.SLASH;
        }

        webFileVo = new WebFileVo();
        webFileVo.setOldName(fileName);
        try {
            String suffixName = suffix(fileName);
            String uuid = generateUUID();
            String newPath = rename(uuid, suffixName, savePath);

            webFileVo.setNewName(uuid + suffixName);

            File newFile = new File(newPath);
            createDirectory(savePath);
            multipartFile.transferTo(newFile);

            webFileVo.setPath(newPath);

            return webFileVo;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 多文件上传
     *
     * @param tagName 页面控件名称
     * @return
     */
    public static List<WebFileVo> upload(HttpServletRequest request, String tagName, String savePath) {
        List<WebFileVo> list = new ArrayList<>();
        List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles(tagName);
        if (null != files && !files.isEmpty()) {
            for (MultipartFile multipartFile : files) {
                WebFileVo tempBean = upload(multipartFile, savePath);
                list.add(tempBean);
            }
        }
        return list;
    }


    /**
     * 上传文件重命名
     *
     * @param suffixName
     * @param savePath
     * @return
     */
    private static String rename(String uuid, String suffixName, String savePath) {
        return savePath + uuid + suffixName;
    }

    /**
     * 获取UUID
     *
     * @return
     */
    private static String generateUUID() {
        String str = String.valueOf(UUID.randomUUID());
        while (str.indexOf(SEPARATE_HR) >= 0) {
            str = str.replace(SEPARATE_HR, StringHelper.EMPTY);
        }
        return str;
    }

    /**
     * 默认获取后缀
     *
     * @param fileName
     * @return
     */
    private static String suffix(String fileName) {
        return fileName.substring(fileName.lastIndexOf(SEPARATE_SPOT));
    }
}