package com.apobates.forum.thrones.controller.helper;

import com.apobates.forum.utils.image.OverlayBox.OverlayConfig;
import com.apobates.forum.utils.image.OverlayBoxException;
import com.apobates.forum.utils.zxing.GeneralQRCode;
import com.apobates.forum.utils.zxing.GeneralQRCode.GeneralQRCodeBuilder;
import com.apobates.forum.utils.zxing.GeneralQRCode.ImageType;
import com.google.zxing.WriterException;
import java.io.File;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.Objects;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 话题二维码文件
 * @author xiaofanku
 * @since 20200525
 */
public class TopicQRCodeFile {
    private final GeneralQRCodeBuilder qRCodeBuilder;
    private final File logoPath;
    private final OverlayConfig config;
    private final static Logger logger = LoggerFactory.getLogger(TopicQRCodeFile.class);
    
    private TopicQRCodeFile(GeneralQRCodeBuilder qRCodeBuilder, File logoPath, OverlayConfig config) {
        this.qRCodeBuilder = qRCodeBuilder;
        this.logoPath = logoPath;
        this.config = config;
    }
    /**
     * 生成临时文件的二维码
     * @return 
     */
    public Optional<File> create() {
        try {
            GeneralQRCode qc = qRCodeBuilder.build();
            File tmpFile = createTempFile(qc.getImage().getType());
            if (null == logoPath) { //没有设置logo图片
                qc.toFile(tmpFile);
            } else { //有设置logo图片
                try (PipedOutputStream outputStream = new PipedOutputStream(); PipedInputStream inputStream = new PipedInputStream(outputStream)) { //20200329@AutoCloseable
                    qc.toStream(outputStream);
                    try {
                        config.image(logoPath).toFile(inputStream, tmpFile.toPath());
                    } catch (NullPointerException e) {
                        OverlayConfig.getDefault().isContinueSave(true).image(logoPath).toFile(inputStream, tmpFile.toPath());
                    }
                }
            }
            return Optional.ofNullable(tmpFile);
        } catch (OverlayBoxException | WriterException | IOException e) {
            if(logger.isDebugEnabled()){
                logger.debug("创建话题的二维码文件失败", e);
            }
        }
        return Optional.empty();
    }
    /**
     * 若二维码存在返回,不存在创建二维码文件
     * @param cacheDirect 缓存的目录名称
     * @param topicDirectName 话题的目录名称
     * @return
     */
    public Optional<File> cacheFile(String cacheDirect, String topicDirectName){
        String cacheFilePath = String.format("%s/topic_cache/%s/qrcode.png", cacheDirect, topicDirectName);
        File cacheFile = new File(cacheFilePath);
        if (!cacheFile.exists()) {
            try{
                //创建
                return putCacheFile(cacheFilePath);
            }catch(IOException e){
                throw new IllegalStateException(e);
            }
        }
        return Optional.ofNullable(cacheFile);
    }
    //临时文件
    private File createTempFile(String imageType) throws IOException {
        File file = File.createTempFile("QRCode", "." + imageType);
        file.deleteOnExit();
        return file;
    }
    //缓存文件
    private Optional<File> putCacheFile(String cacheFilePath) throws IOException {
        Objects.requireNonNull(cacheFilePath);
        String cacheFileDirect = cacheFilePath.replace("qrcode.png", "");
        File cacheDirect = new File(cacheFileDirect);
        if (!cacheDirect.exists()) {
            cacheDirect.mkdirs();
        }
        File cacheDirectFile = new File(cacheDirect, "qrcode.png");
        GeneralQRCode qc = qRCodeBuilder.build();
        try{
            if (null == logoPath) { //没有设置logo图片
                qc.toFile(cacheDirectFile);
            } else { //有设置logo图片
                try (PipedOutputStream outputStream = new PipedOutputStream(); PipedInputStream inputStream = new PipedInputStream(outputStream)) { //20200329@AutoCloseable
                    qc.toStream(outputStream);
                    try {
                        config.image(logoPath).toFile(inputStream, cacheDirectFile.toPath());
                    } catch (NullPointerException e) {
                        OverlayConfig.getDefault().isContinueSave(true).image(logoPath).toFile(inputStream, cacheDirectFile.toPath());
                    }
                }
            }
            return Optional.ofNullable(cacheDirectFile);
        }catch(WriterException e){
            if(logger.isDebugEnabled()){
                logger.debug("创建话题的二维码文件失败", e);
            }
        }
        return Optional.empty();
    }
    /**
     * 使用二维码内容初始化一个内部包装类
     *
     * @param content
     * @return
     */
    public static WrapQRCodeBuilder from(String content) {
        return new WrapQRCodeBuilder(content);
    }
    /**
     * 内部包装类.主要包装:二维码主类的构造者类
     *
     * @author xiaofanku
     * @since 20200326
     */
    public static class WrapQRCodeBuilder {
        private final GeneralQRCodeBuilder qrbuilder;
        private final File logoPath;
        private final OverlayConfig config;
        
        /**
         * 用二维码的内容初始化
         *
         * @param content
         */
        public WrapQRCodeBuilder(String content) {
            this.qrbuilder = new GeneralQRCodeBuilder(content);
            this.logoPath = null;
            this.config = null;
        }
        
        private WrapQRCodeBuilder(GeneralQRCodeBuilder qrbuilder, File logoPath, OverlayConfig config) {
            this.qrbuilder = qrbuilder;
            this.logoPath = logoPath;
            this.config = config;
        }
        
        /**
         * 设置二维码的尺码
         *
         * @param width
         * @param height
         * @return
         */
        public WrapQRCodeBuilder scale(int width, int height) {
            GeneralQRCodeBuilder tmp = qrbuilder.withSize(width, height);
            return new WrapQRCodeBuilder(tmp, logoPath, config);
        }
        
        /**
         * 设置二维码图片的文件类型
         *
         * @param type
         * @return
         */
        public WrapQRCodeBuilder format(ImageType type) {
            GeneralQRCodeBuilder tmp = qrbuilder.formatImage(type);
            return new WrapQRCodeBuilder(tmp, logoPath, config);
        }
        
        /**
         * 为二维码增加logo图片<br/>
         * logo图片面积大于100X100可能导致无法解析<br/>
         *
         * @param logoPath
         * @return
         */
        public WrapQRCodeBuilder logo(File logoPath) {
            return new WrapQRCodeBuilder(qrbuilder, logoPath, config);
        }
        
        /**
         * 设置二维码中的logo图片遮盖层
         *
         * @param config
         * @return
         */
        public WrapQRCodeBuilder overlay(OverlayConfig config) {
            return new WrapQRCodeBuilder(qrbuilder, logoPath, config);
        }
        
        /**
         * 实例化一个话题二维码文件
         *
         * @return
         */
        public TopicQRCodeFile toInstance() {
            return new TopicQRCodeFile(this.qrbuilder, this.logoPath, this.config);
        }
    }
}