package com.ruoyi.system.service;

import cn.hutool.core.img.Img;
import cn.hutool.core.lang.UUID;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.system.domain.SysOss;
import com.ruoyi.system.domain.bo.SysOssBo;
import com.ruoyi.system.domain.vo.SysOssVo;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;

/**
 * 文件上传 服务层
 *
 * @author Lion Li
 */
public interface ISysOssService {

    String IMAGE_WEBP="webp";

    TableDataInfo<SysOssVo> queryPageList(SysOssBo sysOss, PageQuery pageQuery);

    List<SysOssVo> listByIds(Collection<Long> ossIds);

    SysOssVo getById(Long ossId);

    SysOssVo upload(MultipartFile file);

    /**
     *
     * @param file
     * @param pre  - 图片保存路径前缀
     * @return
     */
    SysOssVo upload(MultipartFile file,String pre);

    /**
     * 使用默认的最大高宽和水印保存图片
     * @param file
     * @param pre   - 图片保存路径前缀
     * @return
     */
    SysOssVo uploadImgs(MultipartFile file,String pre);


    /**
     *
     * @param file
     * @param pre       - 图片保存路径前缀
     * @param maxWidth  - 缩放到指定的宽 小于1表示不缩放
     * @param maxHeight - 缩放到指定的高 小于1表示不缩放
     * @param watermark - 水印图片 null表示不加水印
     * @return
     */
    SysOssVo uploadImgs(MultipartFile file,String pre, int maxWidth, int maxHeight,
                        BufferedImage watermark);

    void download(Long ossId, HttpServletResponse response) throws IOException;

    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);



    default InputStream formatImage(MultipartFile file, int maxWidth, int maxHeight,
                                    BufferedImage watermark) {
        try {
            if (file == null || file.isEmpty()) {
                throw new RuntimeException("上传图片不能为空");
            }
            if (!file.getContentType().startsWith("image/")) {
                throw new RuntimeException("上传的文件不是图片");
            }
            return formatImage(file.getInputStream(), maxWidth, maxHeight, watermark);
        } catch (IOException e) {
            throw new RuntimeException("处理图片错误", e);
        }
    }

    default InputStream formatImage(Image img, int maxWidth, int maxHeight, BufferedImage watermark) {
        if (img == null) {
            throw new RuntimeException("图片不能为空");
        }
        return formatImage(Img.from(img), maxWidth, maxHeight, watermark);
    }

    default InputStream formatImage(InputStream in,  int maxWidth, int maxHeight, BufferedImage watermark) {
        return formatImage(Img.from(in), maxWidth, maxHeight, watermark);
    }

    default InputStream formatImage(Img img,  int maxWidth, int maxHeight, BufferedImage watermark) {
        try {
            int w = img.getImg().getWidth(null);
            int h = img.getImg().getHeight(null);
            if(maxWidth>0 && maxHeight > 0){
                if (w > maxWidth || h > maxHeight) {
                    int outWidth = 0;
                    int outHeight = 0;
                    outHeight = maxWidth * h / w;
                    if (outHeight > maxHeight) {
                        outHeight = maxHeight;
                        outWidth = outHeight * maxWidth / h;
                    } else {
                        outWidth = maxWidth;
                    }
                    img = img.scale(outWidth, outHeight);
                    w = outWidth;
                    h = outHeight;
                }
            }

            if (watermark != null) {
                int ww = watermark.getWidth(null);
                int wh = watermark.getHeight(null);
                if (w > ww && h > wh) {
                    img = img.pressImage(watermark, 0, 0, 1f);
                }
            }

            ByteArrayOutputStream pout = new ByteArrayOutputStream();

            img.setTargetImageType(IMAGE_WEBP).write(pout);

            ByteArrayInputStream pin = new ByteArrayInputStream(pout.toByteArray());
            pout.close();
            pout = null;
            return pin;
        } catch (Exception e) {
            throw new RuntimeException("处理图片错误", e);
        }
    }



    /**
     * <pre>
     * - 根据存放规则和文件名生成存放的URI
     * - 支持
     * 	- {yyyy}/{MM}/{dd}/{HH}/{mm}/{ss} 年月日时分秒
     * 	- {UUID} 32位的唯一标志
     * 	- {id} int类型的唯一id,防止重复建议+年月日路径
     * 	- {id16} int类型的唯一id16进制表示,防止重复建议+年月日路径
     * 	- {id36} int类型的唯一id36进制表示,防止重复建议+年月日路径
     * 	- {filename} 文件基础名称
     * 	- {ext} 扩展名
     * </pre>
     *
     * @param rule
     * @param filename
     * @return
     */
    default String generateURI(String rule, String filename) {
        Calendar c = Calendar.getInstance();
        if (rule.contains("{yyyy}")) {
            rule = rule.replace("{yyyy}", "" + c.get(Calendar.YEAR));
        }
        if (rule.contains("{MM}")) {
            rule = rule.replace("{MM}", "" + (c.get(Calendar.MONTH) + 1));
        }
        if (rule.contains("{dd}")) {
            rule = rule.replace("{dd}", "" + c.get(Calendar.DATE));
        }
        if (rule.contains("{HH}")) {
            rule = rule.replace("{HH}", "" + c.get(Calendar.HOUR_OF_DAY));
        }
        if (rule.contains("{mm}")) {
            rule = rule.replace("{mm}", "" + c.get(Calendar.MINUTE));
        }
        if (rule.contains("{ss}")) {
            rule = rule.replace("{ss}", "" + c.get(Calendar.SECOND));
        }
        if (rule.contains("{UUID}")) {
            rule = rule.replace("{UUID}", UUID.fastUUID().toString(true));
        }
        if (rule.contains("{id}")) {
            rule = rule.replace("{id}", Integer.toString(id.nextId()));
        }
        if (rule.contains("{id16}")) {
            rule = rule.replace("{id16}", Integer.toString(id.nextId(), 16));
        }
        if (rule.contains("{id36}")) {
            rule = rule.replace("{id36}", Integer.toString(id.nextId(), 36));
        }
        if (rule.contains("{filename}")) {
            String temp = null;
            if (filename.contains(".")) {
                temp = filename.substring(0, filename.lastIndexOf("."));
            } else {
                temp = filename;
            }
            rule = rule.replace("{filename}", temp);
        }

        if (rule.contains("{ext}")) {
            String temp = null;
            if (filename.contains(".")) {
                temp = filename.substring(filename.lastIndexOf(".") + 1);
            } else {
                temp = "";
            }
            rule = rule.replace("{ext}", temp.toLowerCase());
        }
        return rule;
    }
    Id id = new Id();

    static class Id {
        private long lastTimestamp = 0;
        private int sequence = 0;

        public synchronized int nextId() {
            long timestamp = System.currentTimeMillis();
            if (lastTimestamp == timestamp) {
                sequence = (sequence + 1) & 0xF;
                if (sequence == 0) {
                    while (timestamp <= lastTimestamp) {
                        timestamp = System.currentTimeMillis();
                    }
                }
            } else {
                sequence = 0;
            }
            lastTimestamp = timestamp;
            return (int) (timestamp & 0xFFFF) << 8 | sequence;
        }
    }
}
