package com.pcloud.book.group.tools;

import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;

import com.pcloud.common.utils.QrcodeUtils;
import com.pcloud.common.utils.string.StringUtil;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.image.BufferedImage;
import java.io.File;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

/**
 * @author lily
 * @date 2019/3/20 10:14
 */
public class QrcodeTools {
    private static final Logger LOGGER = LoggerFactory.getLogger(QrcodeTools.class);

    public static String reCreateQrcode(String fileUrl) {
        try {
            String qrcodeUrl = decodeQrcode(fileUrl);
            if (StringUtil.isEmpty(qrcodeUrl)) {
                return fileUrl;
            } else {
                return QrcodeUtils.create(qrcodeUrl);
            }
        } catch (Exception e) {
            LOGGER.error("二维码生成失败fileUrl=" + fileUrl);
            return fileUrl;
        }
    }


    public static String decodeQrcode(String fileUrl) {
        BufferedImage image;
        try {
            if(fileUrl.contains("http")){
                image = ImageIO.read(new URL(fileUrl));
            }else{
                image = ImageIO.read(new File(fileUrl));
            }
            return  readToString(image);
        } catch (Exception e) {
            LOGGER.error("识别二维码失败fileUrl="+fileUrl,e);
        }
        return null;
    }

    private static String readToString(BufferedImage sourceImage) {
        BufferedImage image = toGrayImage(sourceImage);
        if (sourceImage.getWidth() > 1500 && sourceImage.getHeight() > 1500) {// second
            image = resizeToMaxSize(sourceImage);
        }
        String result = readDirectly(image);
        if (StringUtils.isNotBlank(result)) {
            return result;
        }
        int minSize = 170;
        int imgSize = Math.min(image.getWidth(), image.getHeight());
        int level = 1;
        while (imgSize > minSize) {
            BufferedImage newImage = new BufferedImage((int) (image.getWidth() * Math.pow(0.9, level)),
                    (int) (image.getHeight() * Math.pow(0.9, level)), image.getType());
            newImage.getGraphics().drawImage(image, 0, 0, newImage.getWidth(), newImage.getHeight(), 0, 0, image.getWidth(),
                    image.getHeight(), null);
            result = readDirectly(newImage);
            if (StringUtils.isNotBlank(result)) {
                return result;
            }
            imgSize = Math.min(newImage.getWidth(), newImage.getHeight());
            level++;
        }
        return "";
    }

    private static String readDirectly(BufferedImage image) {
        LuminanceSource source = new BufferedImageLuminanceSource(image);
        Binarizer binarizer = new HybridBinarizer(source);
        BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
        Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
        hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
        try {
            return new MultiFormatReader().decode(binaryBitmap, hints).getText();
        } catch (NotFoundException e) {
            return "";
        }
    }


    /**
     * 将图片转成灰阶。
     *
     * @param image
     * @return
     */
    private static BufferedImage toGrayImage(BufferedImage image) {
        BufferedImage result = image;
        if (BufferedImage.TYPE_BYTE_GRAY != image.getType()) {
            BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
            newImage.getGraphics().drawImage(image, 0, 0, null);
            result = newImage;
        }
        return result;
    }

    /**
     * 图片若过大，则缩放图片。
     *
     * @param image
     * @return
     */
    private static BufferedImage resizeToMaxSize(BufferedImage image) {
        int height = 1500;
        int width = 1500;
        if (image.getWidth() > image.getHeight()) {
            width = (int) (height * (((double) image.getWidth()) / image.getHeight()));
        } else {
            height = (int) (width * (((double) image.getHeight()) / image.getWidth()));
        }
        BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
        newImage.getGraphics().drawImage(image, 0, 0, newImage.getWidth() + 1, newImage.getHeight() + 1, 0, 0, image.getWidth(),
                image.getHeight(), null);
        return newImage;
    }

    /**
     * @Author:lili
     * @Desr:处理url地址
     * @Date:2019/5/15 11:08
     */
    public static String ossToFile(String newUrl) {
        if(!StringUtil.isEmpty(newUrl)){
            newUrl = newUrl.replace("//oss","//file");
        }
        return newUrl;
    }
}
