package com.yuchen.saas.park.service.util;

import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;

@Slf4j
public class PicToBase64Utils {
    /**
     * 将网络地址对应的图片转换为base64
     *
     * @param imagePath 网络图片路径
     * @return res 图片对应的Base64编码
     */
    public static String imageChangeBase64(String imagePath) {
        ByteArrayOutputStream outPut = new ByteArrayOutputStream();
        byte[] data = new byte[1024];
        try {
            // 创建URL
            URL url = new URL(imagePath);
            // 创建链接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(10 * 1000);

            if (conn.getResponseCode() != 200) {
                return "fail";//连接失败/链接失效/图片不存在
            }
            InputStream inStream = conn.getInputStream();
            int len = -1;
            while ((len = inStream.read(data)) != -1) {
                outPut.write(data, 0, len);
            }
            inStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组Base64编码
        byte[] encode = Base64.getEncoder().encode(outPut.toByteArray());
        String res = new String(encode);
        return res;
    }


    public static byte[] imageChangeByte(String imagePath) {
        ByteArrayOutputStream outPut = null;
        InputStream inStream = null;
        HttpURLConnection conn = null;
        byte[] data = new byte[1024];
        try {
            log.info("根据url获得图片 start");
            // 创建URL
            URL url = new URL(imagePath);
            outPut = new ByteArrayOutputStream();
            // 创建链接
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(10 * 1000);

            if (conn.getResponseCode() != 200) {
                return null;//连接失败/链接失效/图片不存在
            }
            log.info("获得图片输入流 start");
            inStream = conn.getInputStream();
            log.info("获得图片输入流 end");
            int len = -1;
            while ((len = inStream.read(data)) != -1) {
                outPut.write(data, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outPut != null) {
                try {
                    outPut.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (inStream != null) {
                try {
                    inStream.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (conn != null) {
                conn.disconnect();
            }
        }
        // 对字节数组Base64编码
        //byte[] encode = Base64.getEncoder().encode(outPut.toByteArray());
        log.info("根据url获得图片 end");
        return outPut.toByteArray();
    }


    /**
     * 根据指定大小压缩图片
     *
     * @param imageBytes  源图片字节数组
     * @param desFileSize 指定图片大小，单位kb
     * @param imageId     影像编号
     * @return 压缩质量后的图片字节数组
     */
    public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize, String imageId) {
        if (imageBytes == null || imageBytes.length == 0 || imageBytes.length < desFileSize * 1024) {
            return imageBytes;
        }
        long srcSize = imageBytes.length;
        double accuracy = getAccuracy(srcSize / 1024);
        try {
            log.info("压缩图片 start");
            while (imageBytes.length > desFileSize * 1024) {
                ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
                Thumbnails.of(inputStream)
                        .scale(accuracy)
                        .outputQuality(1)
                        .toOutputStream(outputStream);
                imageBytes = outputStream.toByteArray();
            }
            log.info("压缩图片 end");
            log.info("【图片压缩】imageId={} | 图片原大小={}kb | 压缩后大小={}kb",
                    imageId, srcSize / 1024, imageBytes.length / 1024);
        } catch (Exception e) {
            log.error("【图片压缩】msg=图片压缩失败!", e);
        }
        return imageBytes;
    }


    public static String imgChangeStrLimitSize(String imagePath) {
        byte[] bytes = imageChangeByte(imagePath);
        if (bytes == null) {
            throw new RuntimeException("未找到对应图片");
        }
        long desFileSize = 200L;
        int length = bytes.length / 1024;
        if (length < 10) {
            throw new RuntimeException("图片最小不能小于10K");
        }
        if (length <= 200) {
            return new String(Base64.getEncoder().encode(bytes));
        }
        byte[] encode = compressPicForScale(bytes, desFileSize, null);
        // 对字节数组Base64编码
        String result = new String(Base64.getEncoder().encode(encode));
        return result;
    }
    public static String imgChangeStrLimitSize50L(String imagePath) {
        byte[] bytes = imageChangeByte(imagePath);
        if (bytes == null) {
            throw new RuntimeException("未找到对应图片");
        }
        long desFileSize = 50L;
        int length = bytes.length / 1024;
        if (length < 10) {
            throw new RuntimeException("图片最小不能小于10K");
        }
        if (length <= desFileSize) {
            return new String(Base64.getEncoder().encode(bytes));
        }
        byte[] encode = compressPicForScale(bytes, desFileSize, null);
        // 对字节数组Base64编码
        String result = new String(Base64.getEncoder().encode(encode));
        return result;
    }

    /**
     * 自动调节精度(经验数值)
     *
     * @param size 源图片大小
     * @return 图片压缩质量比
     */
    private static double getAccuracy(long size) {
        double accuracy;
        if (size < 900) {
            accuracy = 0.85;
        } else if (size < 2047) {
            accuracy = 0.6;
        } else if (size < 3275) {
            accuracy = 0.44;
        } else {
            accuracy = 0.4;
        }
        return accuracy;
    }


}