package com.jeequan.jeepay.bizcommons.manage.qrshell;

import com.alibaba.fastjson.JSON;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.*;

/***
* ShellC生成器
*
* @author terrfly
* @date 2023/6/26 15:44
*/
@Data
@Service
public class ShellBGenerator extends AbstractGenerator {

    /** 生成二维码图片的 buffer缓冲值 **/
    @Override
    public BufferedImage genQrImgBuffer(String configModelStr, String qrUrlContent, Long qrcId, String mchStoreName, boolean isViewFlag) throws IOException, WriterException {

        CommonConfigModel configModel = JSON.parseObject(configModelStr, CommonConfigModel.class);

        String qrId = "No." + qrcId.toString();

        //图片的宽和高
        int imgWidth = 308 * 3;  //924
        int imgHeight = 450 * 3; //1350

        BufferedImage bufferedImage = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);

        //设置： 二维码背景颜色
        Graphics2D graphic = bufferedImage.createGraphics();
        graphic.setColor( new Color(Integer.parseInt(StringUtils.defaultIfEmpty(configModel.getBgColor(), "#5094d5").substring(1),16)) );//背景色的设置
        graphic.fillRect(0, 0, imgWidth, imgHeight);
        graphic.drawRenderedImage(bufferedImage, null);

        graphic.dispose();


        //logo
        if(StringUtils.isNotEmpty(configModel.getLogoImgUrl() )){

            File imgFile = downloadAndGetCacheFile(configModel.getLogoImgUrl());
            if(imgFile != null){
                //设置：底部logo
                BufferedImage waterLogo = ImageIO.read(imgFile); //水印图片
                graphic = bufferedImage.createGraphics();
                graphic.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1)); //alpha 水印的透明度  0完全透明， 1不透明

                graphic.drawImage(waterLogo, 0 ,  0, 924, 282, null);
                graphic.dispose();
            }
        }


        //设置：二维码背景图
        BufferedImage waterImg = getStaticImg("/shellB/div1.png"); //水印图片
        graphic = bufferedImage.createGraphics();
        graphic.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1)); //alpha 水印的透明度  0完全透明， 1不透明
        graphic.drawImage(waterImg, 98, 282, waterImg.getWidth(), waterImg.getHeight(), null);
        graphic.dispose();

        //设置：二维码背景图
        BufferedImage waterImg2 = getStaticImg("/shellB/div2.png"); //水印图片
        graphic = bufferedImage.createGraphics();
        graphic.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1)); //alpha 水印的透明度  0完全透明， 1不透明
        graphic.drawImage(waterImg2, 98, 1002, waterImg2.getWidth(), waterImg2.getHeight(), null);
        graphic.dispose();


        //设置：二维码 190X190
        //生成真实的二维码图片
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 1); //调整白边边距 1，2,3,4 四个档位
        BitMatrix bitMatrix = new MultiFormatWriter().encode(qrUrlContent, BarcodeFormat.QR_CODE, 540, 540, hints);// 生成矩阵
        BufferedImage waterQrImg = MatrixToImageWriter.toBufferedImage(bitMatrix);

        graphic = bufferedImage.createGraphics();
        graphic.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1)); //alpha 水印的透明度  0完全透明， 1不透明
        graphic.drawImage(waterQrImg, 192, 372, waterQrImg.getWidth(), waterQrImg.getHeight(), null);
        graphic.dispose();


        //二维码中间logo
        if(StringUtils.isNotEmpty(configModel.getQrInnerImgUrl() )){

            File imgFile = downloadAndGetCacheFile(configModel.getQrInnerImgUrl());
            if(imgFile != null){


                //设置：二维码白框
                BufferedImage waterImg3 = getStaticImg("/shellB/div3.png"); //水印图片
                graphic = bufferedImage.createGraphics();
                graphic.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1)); //alpha 水印的透明度  0完全透明， 1不透明
                graphic.drawImage(waterImg3, 417, 597, waterImg3.getWidth(), waterImg3.getHeight(), null);
                graphic.dispose();


                //设置：底部logo
                BufferedImage waterLogo = ImageIO.read(imgFile); //水印图片
                graphic = bufferedImage.createGraphics();
                graphic.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1)); //alpha 水印的透明度  0完全透明， 1不透明
                graphic.drawImage(waterLogo, 422, 602, 80, 80, null);
                graphic.dispose();
            }
        }



        //支付方式
        List<MutablePair<String, BufferedImage>> payTypeImgList = new ArrayList<>();
        if(configModel.getPayTypeList() != null){
            for (CommonConfigModel.PayType payType : configModel.payTypeList) {
                if("unionpay".equals(payType.getName()) || "ysfpay".equals(payType.getName())  ||"wxpay".equals(payType.getName()) || "alipay".equals(payType.getName()) ){
                    payTypeImgList.add(MutablePair.of(payType.getAlias(), getStaticImg("/commons/" + "t_" + payType.getName() + ".png")));
                }else{
                    File imgFile = downloadAndGetCacheFile(payType.getImgUrl()); // 下载图片
                    if(imgFile != null){
                        payTypeImgList.add(MutablePair.of(payType.getAlias(), ImageIO.read(imgFile)));
                    }
                }
            }
        }

        List<int[]> areaArrays = getPayTypeLocation(payTypeImgList.size());
        if(areaArrays != null && !areaArrays.isEmpty()){
            for (int i = 0; i < areaArrays.size() ;i++) {
                BufferedImage waterImg1 = payTypeImgList.get(i).right; //水印图片
                graphic = bufferedImage.createGraphics();
                graphic.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1)); //alpha 水印的透明度  0完全透明， 1不透明
                graphic.drawImage(waterImg1, areaArrays.get(i)[0], areaArrays.get(i)[1], 60, 60, null);
                graphic.dispose();

                String alias = payTypeImgList.get(i).left;
                if(StringUtils.isNotEmpty(alias)){

                    graphic = bufferedImage.createGraphics();
                    graphic.setColor(Color.black);//背景设置为白色

                    Font font = new Font(AbstractGenerator.DEFAULT_FONT, Font.PLAIN, 24);
                    FontMetrics metrics = graphic.getFontMetrics(font);
                    // 字体居中：  文字中间位置（图标位置+20） - 一半的文字正中间位置
                    int x =  ( areaArrays.get(i)[0] + 20 ) - (metrics.stringWidth(alias) / 2) + 10;

                    graphic.setFont(font); //字体、字型、字号
                    graphic.drawString(alias, x, areaArrays.get(i)[1] + 60 + 24 + 16 ); //画文字
                    graphic.drawRenderedImage(bufferedImage, null);
                    graphic.dispose();



                }


            }
        }

        if(configModel.isShowIdFlag()){
            //设置：二维码编号
            graphic = bufferedImage.createGraphics();
            graphic.setColor(Color.black);//背景设置为白色

            Font qrIdFont = new Font(AbstractGenerator.DEFAULT_FONT, Font.PLAIN, 27);
            FontMetrics metrics = graphic.getFontMetrics(qrIdFont);
            int x =  (imgWidth - metrics.stringWidth(qrId)) / 2;

            graphic.setFont(qrIdFont); //字体、字型、字号
            graphic.drawString(qrId , x, 955); //画文字
            graphic.drawRenderedImage(bufferedImage, null);
            graphic.dispose();
        }


        if(configModel.isShowStoreNameFlag() && StringUtils.isNotEmpty(mchStoreName) ){
            //设置：二维码编号
            graphic = bufferedImage.createGraphics();
            graphic.setColor(Color.black);//背景设置为白色

            Font qrIdFont = new Font(AbstractGenerator.DEFAULT_FONT, Font.PLAIN, 42);
            FontMetrics metrics = graphic.getFontMetrics(qrIdFont);
            int x =  (imgWidth - metrics.stringWidth(mchStoreName)) / 2;

            graphic.setFont(qrIdFont); //字体、字型、字号
            graphic.drawString(mchStoreName , x, 355); //画文字
            graphic.drawRenderedImage(bufferedImage, null);
            graphic.dispose();
        }

        // 预览需要缩小三倍
        return isViewFlag ? zoomOutImage(bufferedImage, 2) : bufferedImage;
    }


    public static BufferedImage zoomOutImage(BufferedImage originalImage, Integer times){

        int width = originalImage.getWidth()/times;
        if(width < 0){
            width=originalImage.getWidth();
        }
        int height = originalImage.getHeight()/times;
        if(height < 0){
            height=originalImage.getHeight();
        }
        BufferedImage newImage = new BufferedImage(width,height,originalImage.getType());

        Graphics g = newImage.getGraphics();

        g.drawImage(originalImage, 0,0,width,height,null);

        g.dispose();

        return newImage;

    }


    /**
     *
     * @Title: 构造图片
     * @Description: 生成水印并返回java.awt.image.BufferedImage
     * @param file
     *            源文件(图片)
     * @param waterFile
     *            水印文件(图片)
     * @param x
     *            距离右下角的X偏移量
     * @param y
     *            距离右下角的Y偏移量
     * @param alpha
     *            透明度, 选择值从0.0~1.0: 完全透明~完全不透明
     * @return BufferedImage
     * @throws IOException
     */
    public static BufferedImage watermark(File file, File waterFile, int x, int y, float alpha) throws IOException {
        // 获取底图
        BufferedImage buffImg = ImageIO.read(file);
        // 获取层图
        BufferedImage waterImg = ImageIO.read(waterFile);
        // 创建Graphics2D对象，用在底图对象上绘图
        Graphics2D g2d = buffImg.createGraphics();
        int waterImgWidth = waterImg.getWidth();// 获取层图的宽度
        int waterImgHeight = waterImg.getHeight();// 获取层图的高度
        // 在图形和图像中实现混合和透明效果
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
        // 绘制
        g2d.drawImage(waterImg, x, y, waterImgWidth, waterImgHeight, null);
        g2d.dispose();// 释放图形上下文使用的系统资源
        return buffImg;
    }



    private List<int[]> getPayTypeLocation(int size){

        if(size == 1){
            return Arrays.asList(new int[]{432, 1066});
        }

        if(size == 2){
            return Arrays.asList(new int[]{296, 1066}, new int[]{568, 1066});
        }

        if(size == 3){
            return Arrays.asList(new int[]{207, 1066}, new int[]{432, 1066}, new int[]{657, 1066});
        }

        if(size == 4){
            return Arrays.asList(new int[]{159, 1066}, new int[]{341, 1066}, new int[]{523, 1066}, new int[]{705, 1066});
        }

        return null;
    }

}
