package com.airlock.iam.plugin.configeditor.ui;

import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.plugin.configeditor.ConfigEditorApplication;
import com.airlock.iam.plugin.configeditor.util.ConfigMimeTypes;
import com.airlock.iam.system.config.ConfigFormat;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptAll;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.server.StreamVariable;
import com.vaadin.server.StreamVariable.StreamingEndEvent;
import com.vaadin.server.StreamVariable.StreamingErrorEvent;
import com.vaadin.server.StreamVariable.StreamingProgressEvent;
import com.vaadin.server.StreamVariable.StreamingStartEvent;
import com.vaadin.ui.Html5File;
import com.vaadin.ui.Notification;
import com.vaadin.ui.DragAndDropWrapper.WrapperTransferable;
import com.vaadin.ui.Notification.Type;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.OutputStream;

public class FileDropHandler implements DropHandler {
   private static final ELogger LOG = ELoggerFactory.getLogger(FileDropHandler.class);
   private final ConfigEditorApplication app;

   public FileDropHandler(ConfigEditorApplication app) {
      this.app = app;
   }

   public void drop(DragAndDropEvent event) {
      if (event.getTransferable() instanceof WrapperTransferable transferable) {
         Html5File[] files = transferable.getFiles();
         if (files == null || files.length == 0) {
            return;
         }

         if (files.length > 1) {
            Notification.show("Please upload a single file.", Type.ERROR_MESSAGE);
            return;
         }

         Html5File file = files[0];
         String mimeType = file.getType();
         ConfigFormat configFormat = ConfigMimeTypes.configFormatForMimeType(mimeType);
         LOG.info("Uploading config file. Mime type is '" + mimeType + "'. Assuming config format " + configFormat);
         file.setStreamVariable(this.buildStreamVariable(configFormat));
      }
   }

   private StreamVariable buildStreamVariable(final ConfigFormat configFormat) {
      final ByteArrayOutputStream bas = new ByteArrayOutputStream();
      return new StreamVariable() {
         public OutputStream getOutputStream() {
            return bas;
         }

         public boolean listenProgress() {
            return false;
         }

         public void onProgress(StreamingProgressEvent event) {
         }

         public void streamingStarted(StreamingStartEvent event) {
         }

         public void streamingFinished(StreamingEndEvent event) {
            byte[] byteArray = bas.toByteArray();
            File uploadedFile = ConfigUtil.createTempFile(byteArray, "uploaded-config").toFile();
            FileDropHandler.this.app.loadUploadedConfigOrImportSnippet(uploadedFile, configFormat);
         }

         public void streamingFailed(StreamingErrorEvent event) {
            Notification.show("Upload failed.", Type.ERROR_MESSAGE);
         }

         public boolean isInterrupted() {
            return false;
         }
      };
   }

   public AcceptCriterion getAcceptCriterion() {
      return AcceptAll.get();
   }
}
