package mara.mybox.controller;

import java.awt.image.BufferedImage;
import java.io.File;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Toggle;
import mara.mybox.db.data.VisitHistory;
import mara.mybox.dev.MyBoxLog;
import mara.mybox.fxml.FxTask;
import mara.mybox.image.data.ImageAttributes;
import mara.mybox.image.file.ImageFileWriters;
import mara.mybox.image.tools.ImageConvertTools;
import mara.mybox.tools.FileNameTools;
import static mara.mybox.value.Languages.message;
import mara.mybox.value.UserConfig;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

/**
 * @Author Mara
 * @CreateDate 2018-6-16
 * @Description
 * @License Apache License Version 2.0
 */
public class PdfConvertImagesBatchController extends BaseBatchPdfController {

    protected ImageAttributes attributes;
    protected PDFRenderer renderer;

    @FXML
    protected ControlImageFormat formatController;
    @FXML
    protected CheckBox transparentBackgroundCheck,
            appendColorCheck, appendCompressionCheck, appendQualityCheck, appendDensityCheck;

    public PdfConvertImagesBatchController() {
        baseTitle = message("PdfConvertImagesBatch");
    }

    @Override
    public void setFileType() {
        setFileType(VisitHistory.FileType.PDF, VisitHistory.FileType.Image);
    }

    @Override
    public void initControls() {
        try {
            super.initControls();

            formatController.setParameters(this, true);

            formatController.formatGroup.selectedToggleProperty().addListener(new ChangeListener<Toggle>() {
                @Override
                public void changed(ObservableValue v, Toggle oldV, Toggle newV) {
                    transparentBackgroundCheck.setVisible(formatController.pngRadio.isSelected() || formatController.tifRadio.isSelected());
                }
            });
            transparentBackgroundCheck.setVisible(formatController.pngRadio.isSelected() || formatController.tifRadio.isSelected());

            transparentBackgroundCheck.setSelected(UserConfig.getBoolean(baseName + "TransparentBackground", false));
            transparentBackgroundCheck.selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue ov, Boolean oldValue, Boolean newValue) {
                    UserConfig.setBoolean(baseName + "TransparentBackground", transparentBackgroundCheck.isSelected());
                }
            });

            startButton.disableProperty().unbind();
            startButton.disableProperty().bind(Bindings.isEmpty(tableView.getItems())
                    .or(formatController.qualitySelector.getEditor().styleProperty().isEqualTo(UserConfig.badStyle()))
                    .or(formatController.dpiSelector.getEditor().styleProperty().isEqualTo(UserConfig.badStyle()))
                    .or(formatController.profileInput.styleProperty().isEqualTo(UserConfig.badStyle()))
                    .or(formatController.binaryController.thresholdInput.styleProperty().isEqualTo(UserConfig.badStyle()))
            );

        } catch (Exception e) {
            MyBoxLog.error(e);
        }
    }

    @Override
    public void initTargetSection() {
        try {
            super.initTargetSection();

            appendColorCheck.selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> v,
                        Boolean oldV, Boolean newV) {
                    UserConfig.setBoolean("PdfConverterAppendColor", appendColorCheck.isSelected());
                }
            });
            appendColorCheck.setSelected(UserConfig.getBoolean("PdfConverterAppendColor"));

            appendCompressionCheck.selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> v,
                        Boolean oldV, Boolean newV) {
                    UserConfig.setBoolean("PdfConverterAppendCompression", appendCompressionCheck.isSelected());
                }
            });
            appendCompressionCheck.setSelected(UserConfig.getBoolean("PdfConverterAppendCompression"));

            appendQualityCheck.selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> v,
                        Boolean oldV, Boolean newV) {
                    UserConfig.setBoolean("PdfConverterAppendQuality", appendQualityCheck.isSelected());
                }
            });
            appendQualityCheck.setSelected(UserConfig.getBoolean("PdfConverterAppendQuality"));

            appendDensityCheck.selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> v,
                        Boolean oldV, Boolean newV) {
                    UserConfig.setBoolean("PdfConverterAppendDensity", appendDensityCheck.isSelected());
                }
            });
            appendDensityCheck.setSelected(UserConfig.getBoolean("PdfConverterAppendDensity"));

        } catch (Exception e) {
            MyBoxLog.debug(e);
        }
    }

    @Override
    public boolean makeActualParameters() {
        if (!super.makeActualParameters()) {
            return false;
        }

        attributes = formatController.attributes;

        return true;
    }

    @Override
    public boolean preHandlePages(FxTask currentTask) {
        try {
            renderer = new PDFRenderer(doc);
        } catch (Exception e) {
            MyBoxLog.error(e);
            renderer = null;
        }
        return renderer != null;
    }

    @Override
    public int handleCurrentPage(FxTask currentTask) {
        try {
            File tFile = makeTargetFile();
            ImageType imageType = ImageType.RGB;
            if (formatController.pngRadio.isSelected() || formatController.tifRadio.isSelected()) {
                if (transparentBackgroundCheck.isSelected()) {
                    imageType = ImageType.ARGB;
                }
            }
            BufferedImage pageImage = renderer.renderImageWithDPI(pageIndex, // 0-based
                    attributes.getDensity(), imageType);
            String targetFormat = attributes.getImageFormat();
            if ("ico".equals(targetFormat) || "icon".equals(targetFormat)) {
                if (ImageConvertTools.convertToIcon(currentTask, pageImage, attributes, tFile)) {
                    targetFileGenerated(tFile);
                    return 1;
                } else {
                    return 0;
                }
            } else {
                BufferedImage targetImage
                        = ImageConvertTools.convertColorSpace(currentTask, pageImage, attributes);
                if (targetImage == null) {
                    return 0;
                }
                if (!ImageFileWriters.writeImageFile(currentTask, targetImage, attributes, tFile.getAbsolutePath())) {
                    return 0;
                }
                targetFileGenerated(tFile);
                return 1;
            }
        } catch (Exception e) {
            MyBoxLog.error(e);
            return 0;
        }
    }

    @Override
    public File makeTargetFile() {
        try {
            String namePrefix = FileNameTools.prefix(currentSourceFile().getName())
                    + "_page" + (pageIndex + 1);
            if (!"ico".equals(attributes.getImageFormat())) {
                if (appendColorCheck.isSelected()) {
                    if (message("IccProfile").equals(attributes.getColorSpaceName())) {
                        namePrefix += "_" + attributes.getProfileName();
                    } else {
                        namePrefix += "_" + attributes.getColorSpaceName();
                    }
                }
                if (attributes.getCompressionType() != null) {
                    if (appendCompressionCheck.isSelected()) {
                        namePrefix += "_" + attributes.getCompressionType();
                    }
                    if (appendQualityCheck.isSelected()) {
                        namePrefix += "_quality-" + attributes.getQuality() + "%";
                    }
                }
                if (appendDensityCheck.isSelected()) {
                    namePrefix += "_" + attributes.getDensity();
                }
            }
            namePrefix = namePrefix.replace(" ", "_");
            String nameSuffix = "." + attributes.getImageFormat();

            return makeTargetFile(namePrefix, nameSuffix, currentParameters.currentTargetPath);
        } catch (Exception e) {
            MyBoxLog.error(e);
            return null;
        }
    }

    @Override
    public void postHandlePages(FxTask currentTask) {
        renderer = null;
    }

}
