package xdean.tool.sys.clipboard;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Optional;
import java.util.function.Supplier;

import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;

import javax.imageio.ImageIO;

import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import xdean.jex.extra.Wrapper;
import xdean.jex.util.security.SecurityUtil;
import xdean.tool.api.Context;

import com.sun.javafx.application.PlatformImpl;

@UtilityClass
public class ClipUtil {

  private final Path TEMP_PATH = Context.TEMP_PATH.resolve("clip");
  private Clipboard CLIPBOARD;
  static {
    try {
      if (Files.notExists(TEMP_PATH)) {
        Files.createDirectory(TEMP_PATH);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
    PlatformImpl.startup(() -> CLIPBOARD = Clipboard.getSystemClipboard());
  }

  private SimpleDateFormat dateFormat = new SimpleDateFormat("MMddHHmmssSSS");

  public Optional<String> getClipText() {
    return getFX(() -> Optional.ofNullable(CLIPBOARD.getString()));
  }

  public void setClipText(String string) {
    runFX(() -> {
      ClipboardContent content = new ClipboardContent();
      content.putString(string);
      CLIPBOARD.setContent(content);
    });
  }

  public Optional<Image> getClipImage() {
    return getFX(() -> Optional.ofNullable(CLIPBOARD.getImage()));
  }

  public void setClipImage(final Image image) {
    runFX(() -> {
      ClipboardContent content = new ClipboardContent();
      content.putImage(image);
      CLIPBOARD.setContent(content);
    });
  }

  public String saveImage(BufferedImage image) throws IOException {
    String name = ClipUtil.normalizeTextLength(String.format("Image%s.png", dateFormat.format(new Date())));
    ImageIO.write(image, "png", new File(TEMP_PATH.toString(), name));
    image.flush();
    return name;
  }

  public Image loadImage(String name) throws IOException {
    BufferedImage swingImage = ImageIO.read(new File(TEMP_PATH.toString(), name));
    return SwingFXUtils.toFXImage(swingImage, null);
  }

  public void cleanImage() {
    try {
      Files.newDirectoryStream(TEMP_PATH).forEach(path -> {
        if (path.getFileName().toString().matches("Image.*\\.jpg")) {
          try {
            Files.deleteIfExists(path);
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      });
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public String normalizeTextLength(String str) {
    if (str.length() < 30) {
      return str;
    }
    return str.substring(0, 25) + "...";
  }

  public BufferedImage toBufferedImage(Image image) {
    return SwingFXUtils.fromFXImage(image, null);
  }

  @SneakyThrows(IOException.class)
  public String md5(BufferedImage image) {
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    ImageIO.write(image, "png", os);
    InputStream fis = new ByteArrayInputStream(os.toByteArray());
    return SecurityUtil.md5(fis);
  }

  private <T> T getFX(Supplier<T> sup) {
    Wrapper<T> wrapper = Wrapper.of(null);
    PlatformImpl.runAndWait(() -> wrapper.set(sup.get()));
    return wrapper.get();
  }

  private void runFX(Runnable r) {
    PlatformImpl.runAndWait(r);
  }
}

@@ -26,24 +26,101 @@
 ipboard;%0D%0A%0D%0A
+import static xdean.jex.util.function.FunctionAdapter.supplierToRunnable;%0D%0A%0D%0A
 import java.
@@ -137,32 +137,32 @@
 BufferedImage;%0D%0A
-
 import java.io.B
@@ -754,41 +754,8 @@
 s;%0D%0A
-import xdean.jex.extra.Wrapper;%0D%0A
 impo
@@ -1352,16 +1352,20 @@
 Format(%22
+yyyy
 MMddHHmm
@@ -2125,17 +2125,8 @@
 e = 
-ClipUtil.
 norm
@@ -3541,51 +3541,38 @@
     
-Wrapper%3CT%3E wrapper = Wrapper.of(null);%0D%0A   
+return supplierToRunnable(sup,
  Pla
@@ -3572,33 +3572,34 @@
 up, PlatformImpl
-.
+::
 runAndWait(() -%3E
@@ -3596,64 +3596,8 @@
 Wait
-(() -%3E wrapper.set(sup.get()));%0D%0A    return wrapper.get(
 );%0D%0A

use functionadapter, little change