package com.xueyi.system.utils.common;

import com.google.common.collect.ImmutableMap;
import com.xueyi.file.api.feign.RemoteFileService;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Component
public class ImageUtil {
	public Map<String, Integer> getCoordinate(Integer cutWidth, Integer cutHeight, Integer x, Integer y, Float rate) {
		if (rate <= 0) {
			rate = 1f;
		}
		Float w = cutWidth * rate;
		Float h = cutHeight * rate;

		Integer w1 = w.intValue();
		Integer h1 = h.intValue();

		Integer addWidth = Math.abs(w1 - cutWidth);
		Integer addHight = Math.abs(h1 - cutHeight);

		Integer addLeftWidth = addWidth / 2;
		Integer addTopHeight = addHight / 2;
		//左边加宽
		if ((x - addLeftWidth) <= 0) {
			x = 0;
		} else {
			x = x - addLeftWidth;
		}

		//左边加宽
		if ((y - addTopHeight) <= 0) {
			y = 0;
		} else {
			y = y - addTopHeight;
		}

		System.out.println("x= " + x);
		System.out.println("y= " + y);
		System.out.println("w= " + w1);
		System.out.println("d= " + h1);
		return ImmutableMap.of("x", x, "y", y, "width", w1, "height", h1);

	}

	public void rectImage(InputStream inputStream, Integer width, Integer height, Integer x, Integer y, Float rate, String savePath) {
		Map<String, Integer> rectMap = getCoordinate(width, height, x, y, rate);
		try {
			Thumbnails.of(inputStream)
					.sourceRegion(rectMap.get("x"), rectMap.get("y"), rectMap.get("width"), rectMap.get("height"))
					.scale(1d)
					.toFile(savePath);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static Boolean checkPixel(InputStream in, Integer maxWidth, Integer maxHeight) {
		try {
			BufferedImage image = ImageIO.read(in);

			if (null == image) {
				return false;
			}

			if (image.getWidth() > maxWidth) {
				return false;
			}
			return image.getHeight() <= maxHeight;
		} catch (IOException e) {
			return false;
		}
	}


	public static Map<String, Integer> fixPixel(InputStream in, Integer maxHeight) {
		try {
			BufferedImage image = ImageIO.read(in);
			Map<String, Integer> map = new HashMap<>();
			if (null == image) {
				return null;
			}

			if (image.getHeight() > maxHeight) {
				map.put("h", 1000);
				map.put("w", (int) Math.floor(1000*image.getWidth()/ image.getHeight()));
			} else {
				map.put("h", image.getHeight());
				map.put("w", image.getWidth());
			}
			return map;
		} catch (IOException e) {
			return null;
		}
	}

	protected String getNewFileName(String ext){
		String random1 = String.valueOf(System.currentTimeMillis());
		String random2 = UUID.randomUUID().toString().replaceAll("-", "");
		return random1 + "_" + random2.substring(0, 8) + "."+ext;
	}



	/**
	 * bytes 转换成Base64字符串
	 *
	 * @param bytes
	 */
	public static String convertToBase64(byte[] bytes) {
		// 对字节数组进行Base64编码，得到Base64编码的字符串
		Base64 base64 = new Base64();
		String base64Str = base64.encodeToString(bytes);
		/*BASE64Encoder encoder = new BASE64Encoder();
		String base64Str = encoder.encode(bytes);*/
		return base64Str;
	}

	/**
	 * stream 转换成Base64字符串
	 *
	 * @param inStream
	 */
	public static String convertToBase64(InputStream inStream) throws Exception {
		// 对字节数组进行Base64编码，得到Base64编码的字符串
		byte[] data = null;

		try {
			ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
			byte[] buff = new byte[100];
			int rc = 0;
			while ((rc = inStream.read(buff, 0, 100)) > 0) {
				swapStream.write(buff, 0, rc);
			}
			data = swapStream.toByteArray();
			return Base64.encodeBase64String(data);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (inStream != null) {
				try {
					inStream.close();
				} catch (IOException e) {
					throw new Exception("输入流关闭异常");
				}
			}
		}

		return null;
	}

	/**
	 * 本地文件（图片、excel等）转换成Base64字符串
	 *
	 * @param imgPath
	 */
	public static String convertFileToBase64(String imgPath) {
		String base64Str = "";
		// 读取图片字节数组
		try {
			InputStream in = new FileInputStream(imgPath);
			base64Str = convertToBase64(in);
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return base64Str;
	}


	public static void fileToOutputStream(String filePath, OutputStream outputStream) {
		try {
			System.err.println(filePath);
			BufferedImage bufferedImage = ImageIO.read(new File(filePath));
			/*
			 * 区别就是以一句，输出到输出流中，如果第三个参数是 File，则输出到文件中
			 */
			ImageIO.write(bufferedImage, "png", outputStream);
			System.err.println("图片生成到输出流成功...");
		} catch (Exception e) {
			e.printStackTrace();
			System.err.println("发生错误: {}!"+e.getMessage());
		}
	}


	@Autowired
	RemoteFileService remoteFileService;

	/**
	 * @Author yangkai
	 * @Description // base64图片转MultipartFile
	 * @Param [imgStr]
	 * @return MultipartFile
	 **/
	public MultipartFile base64ToMultipartFile(String imgStr){

		java.util.Base64.Decoder decoder = java.util.Base64.getDecoder();
		try {
			//Base64解码
			byte[] bytes = decoder.decode(imgStr);
			for (int i = 0; i < bytes.length; ++i) {
				if (bytes[i] < 0) {//调整异常数据
					bytes[i] += 256;
				}
			}

			String newFileName = getNewFileName("jpg");
			ByteArrayInputStream fileStream = new ByteArrayInputStream(bytes);

			Map<String,Integer> map = ImageUtil.fixPixel(fileStream, 1000);

			Integer h = map.get("h");
			Integer w = map.get("w");
			String path = "/tmp";
			FileCopyUtils.copy(bytes, new File(path + "/" + newFileName));

			String savePath = path + "/compress" + newFileName.split("\\?s=")[0];

			File file = new File(path + "/" + newFileName);
			Thumbnails.of(file).size(w,h).outputQuality(0.7).toFile(savePath);

			return getMultipartFile(file);

		} catch (Exception e) {
			return null;
		}
	}

	public static MultipartFile getMultipartFile(File file) {
		FileItem item = new DiskFileItemFactory().createItem("file"
				, MediaType.MULTIPART_FORM_DATA_VALUE
				, true
				, file.getName());
		try (InputStream input = new FileInputStream(file);
			 OutputStream os = item.getOutputStream()) {
			// 流转移
			IOUtils.copy(input, os);
		} catch (Exception e) {
			throw new IllegalArgumentException("Invalid file: " + e, e);
		}

		return new CommonsMultipartFile(item);
	}

	/*/**
	 * @Author yangkai
	 * @Description //将url指向的图片转成为base64格式
	 * @Date 2023/4/24
	 * @Param [imageUrl]
	 * @return java.lang.String base64图片
	 **/
	public static String urlImageToBase64(String imageUrl){
		String base64Image = "";
		try {
			URL url = new URL(imageUrl);
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
			byte[] chunk = new byte[4096];
			int bytesRead;
			InputStream inputStream = url.openStream();
			while ((bytesRead = inputStream.read(chunk)) > 0) {
				outputStream.write(chunk, 0, bytesRead);
			}
			inputStream.close();
			byte[] imageBytes = outputStream.toByteArray();
			base64Image = java.util.Base64.getEncoder().encodeToString(imageBytes);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return base64Image;
	}
}
