/*******************************************************************************
 * Copyright (c) 2011 BSI Business Systems Integration AG.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     BSI Business Systems Integration AG - initial API and implementation
 *******************************************************************************/
package org.eclipse.scout.rt.ui.rap.form.fields.filechooserfield;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.rap.addons.fileupload.DiskFileUploadReceiver;
import org.eclipse.rap.addons.fileupload.FileUploadEvent;
import org.eclipse.rap.addons.fileupload.FileUploadHandler;
import org.eclipse.rap.addons.fileupload.FileUploadListener;
import org.eclipse.rap.addons.fileupload.FileUploadReceiver;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.service.ServerPushSession;
import org.eclipse.scout.commons.CompareUtility;
import org.eclipse.scout.commons.StringUtility;
import org.eclipse.scout.commons.exception.IProcessingStatus;
import org.eclipse.scout.commons.exception.ProcessingStatus;
import org.eclipse.scout.commons.holders.Holder;
import org.eclipse.scout.commons.job.JobEx;
import org.eclipse.scout.commons.logger.IScoutLogger;
import org.eclipse.scout.commons.logger.ScoutLogManager;
import org.eclipse.scout.rt.client.ui.action.menu.root.IContextMenu;
import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
import org.eclipse.scout.rt.client.ui.form.fields.ScoutFieldStatus;
import org.eclipse.scout.rt.client.ui.form.fields.filechooserfield.IFileChooserField;
import org.eclipse.scout.rt.ui.rap.LogicalGridLayout;
import org.eclipse.scout.rt.ui.rap.RwtMenuUtility;
import org.eclipse.scout.rt.ui.rap.action.menu.RwtContextMenuMarkerComposite;
import org.eclipse.scout.rt.ui.rap.action.menu.RwtScoutContextMenu;
import org.eclipse.scout.rt.ui.rap.ext.DropDownFileUpload;
import org.eclipse.scout.rt.ui.rap.ext.StatusLabelEx;
import org.eclipse.scout.rt.ui.rap.ext.StyledTextEx;
import org.eclipse.scout.rt.ui.rap.ext.custom.StyledText;
import org.eclipse.scout.rt.ui.rap.form.fields.LogicalGridDataBuilder;
import org.eclipse.scout.rt.ui.rap.form.fields.RwtScoutValueFieldComposite;
import org.eclipse.scout.rt.ui.rap.internal.TextFieldEditableSupport;
import org.eclipse.scout.rt.ui.rap.keystroke.IRwtKeyStroke;
import org.eclipse.scout.rt.ui.rap.keystroke.RwtKeyStroke;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ProgressBar;

public class RwtScoutFileUploadField extends RwtScoutValueFieldComposite<IFileChooserField> implements IRwtScoutFileUploadField {
  private static final IScoutLogger LOG = ScoutLogManager.getLogger(RwtScoutFileUploadField.class);

  private Composite m_fileContainer;
  private DropDownFileUpload m_browseButton;
  private ProgressBar m_progressBar;
  private TextFieldEditableSupport m_editableSupport;

  private FileUploadHandler m_handler;
  private P_FileUploadListener m_uploadListener;
  private File m_uploadedFile = null;
  private String m_originalVariant = "";

  private RwtContextMenuMarkerComposite m_menuMarkerComposite;
  private RwtScoutContextMenu m_uiContextMenu;
  private P_ContextMenuPropertyListener m_contextMenuPropertyListener;

  public RwtScoutFileUploadField() {
    initializeFileUpload();
  }

  @Override
  protected void initializeUi(Composite parent) {
    super.initializeUi(parent);
    Composite container = getUiEnvironment().getFormToolkit().createComposite(parent);
    StatusLabelEx label = getUiEnvironment().getFormToolkit().createStatusLabel(container, getScoutObject());

    m_fileContainer = getUiEnvironment().getFormToolkit().createComposite(container, SWT.BORDER);
    m_fileContainer.setData(RWT.CUSTOM_VARIANT, VARIANT_FILECHOOSER);

    m_menuMarkerComposite = new RwtContextMenuMarkerComposite(m_fileContainer, getUiEnvironment(), SWT.NONE);
    getUiEnvironment().getFormToolkit().adapt(m_menuMarkerComposite);
    m_menuMarkerComposite.addSelectionListener(new SelectionAdapter() {
      private static final long serialVersionUID = 1L;

      @Override
      public void widgetSelected(SelectionEvent e) {
        if (getUiContextMenu() != null) {
          Menu uiMenu = getUiContextMenu().getUiMenu();
          if (e.widget instanceof Control) {
            Point loc = ((Control) e.widget).toDisplay(e.x, e.y);
            uiMenu.setLocation(RwtMenuUtility.getMenuLocation(getScoutObject().getContextMenu().getChildActions(), uiMenu, loc, getUiEnvironment()));
          }
          uiMenu.setVisible(true);
        }
      }
    });

    StyledText textField = new StyledTextEx(m_menuMarkerComposite, SWT.SINGLE | getUiEnvironment().getFormToolkit().getOrientation()) {
      private static final long serialVersionUID = 1L;

      @Override
      public void setBackground(Color color) {
        if (getUiProgressBar() != null && !getUiProgressBar().isDisposed()) {
          getUiProgressBar().setBackground(color);
        }
        if (getUiBrowseButton() != null && !getUiBrowseButton().isDisposed()) {
          getUiBrowseButton().setBackground(color);
        }
      }
    };
    getUiEnvironment().getFormToolkit().adapt(textField, false, false);
    // correction to look like a normal text
    textField.setData(RWT.CUSTOM_VARIANT, VARIANT_FILECHOOSER);
    //textfield must be disabled. We can't upload the file from it for now.
    textField.setEnabled(false);

    setUiContainer(container);
    setUiLabel(label);
    setUiField(textField);

    createBrowseButton();

    // prevent the button from grabbing focus
    m_fileContainer.setTabList(new Control[]{m_menuMarkerComposite});

    // layout
    container.setLayout(new LogicalGridLayout(1, 0));

    m_fileContainer.setLayoutData(LogicalGridDataBuilder.createField(((IFormField) getScoutObject()).getGridData()));
    m_fileContainer.setLayout(new FormLayout());

    final FormData textLayoutData = new FormData(SWT.DEFAULT, SWT.DEFAULT);
    textLayoutData.left = new FormAttachment(0, 0);
    textLayoutData.right = new FormAttachment(100, -20);
    textLayoutData.bottom = new FormAttachment(m_menuMarkerComposite, -1, SWT.BOTTOM);
    m_menuMarkerComposite.setLayoutData(textLayoutData);
  }

  private void createBrowseButton() {
    m_browseButton = getUiEnvironment().getFormToolkit().createDropDownFileUpload(m_fileContainer, SWT.DROP_DOWN);
    m_browseButton.setData(RWT.CUSTOM_VARIANT, VARIANT_FILECHOOSER);
    // to ensure the text is validated on a context menu call this mouse
    // listener is used.
    m_browseButton.addMouseListener(new MouseAdapter() {
      private static final long serialVersionUID = 1L;

      @Override
      public void mouseDown(MouseEvent e) {
        handleUiInputVerifier(true);
      }
    });
    m_browseButton.addFocusListener(new FocusAdapter() {
      private static final long serialVersionUID = 1L;

      @Override
      public void focusGained(FocusEvent e) {
        getUiField().setFocus();
      }
    });
    setBackgroundFromScout(getScoutObject().getBackgroundColor());

    getUiBrowseButton().addSelectionListener(new SelectionAdapter() {
      private static final long serialVersionUID = 1L;

      @Override
      public void widgetSelected(SelectionEvent event) {
        String filename = getUiBrowseButton().getFileName();
        if (filename == null) {
          return;
        }

        getUiField().setText(filename);
        handleUpload();
      }
    });

    final FormData buttonLayoutData = new FormData(SWT.DEFAULT, SWT.DEFAULT);
    buttonLayoutData.left = new FormAttachment(m_menuMarkerComposite, 0, SWT.RIGHT);
    buttonLayoutData.bottom = new FormAttachment((Control) getUiBrowseButton(), 0, SWT.BOTTOM);
    buttonLayoutData.height = 20;
    buttonLayoutData.width = 20;
    getUiBrowseButton().setLayoutData(buttonLayoutData);

    setEnabledFromScout(getScoutObject().isEnabled());
//    m_browseButton.setDropdownEnabled(calculateDropDownButtonEnabled());
    m_fileContainer.layout();
  }

  private void createProgressBar() {
    m_progressBar = new ProgressBar(m_fileContainer, SWT.HORIZONTAL | SWT.SMOOTH | getUiEnvironment().getFormToolkit().getOrientation());
    getUiEnvironment().getFormToolkit().adapt(m_progressBar, true, true);
    setBackgroundFromScout(getScoutObject().getBackgroundColor());

    final FormData progressLayoutData = new FormData(SWT.DEFAULT, SWT.DEFAULT);
    progressLayoutData.right = new FormAttachment(100, -20);
    progressLayoutData.left = new FormAttachment(0, 0);
    progressLayoutData.top = new FormAttachment(2, 0);
    progressLayoutData.bottom = new FormAttachment(m_progressBar, 4, SWT.BOTTOM);
    m_progressBar.setLayoutData(progressLayoutData);

    m_fileContainer.layout();
  }

  @Override
  public void handleUiDispose() {
    super.handleUiDispose();
    if (m_uploadListener != null) {
      m_uploadListener.cancelUpload();
      m_handler.removeUploadListener(m_uploadListener);
      m_uploadListener = null;
    }
    if (m_handler != null) {
      m_handler.dispose();
      m_handler = null;
    }
    if (m_browseButton != null) {
      m_browseButton.dispose();
      m_browseButton = null;
    }
  }

  private void initializeFileUpload() {
    FileUploadReceiver receiver = new DiskFileUploadReceiver();
    m_handler = new FileUploadHandler(receiver);
  }

  @Override
  public DropDownFileUpload getUiBrowseButton() {
    return m_browseButton;
  }

  @Override
  public ProgressBar getUiProgressBar() {
    return m_progressBar;
  }

  @Override
  public StyledText getUiField() {
    return (StyledText) super.getUiField();
  }

  public RwtScoutContextMenu getUiContextMenu() {
    return m_uiContextMenu;
  }

  @Override
  protected IRwtKeyStroke[] getUiKeyStrokes() {
    return new IRwtKeyStroke[]{
        new RwtKeyStroke(SWT.ESC) {
          @Override
          public void handleUiAction(Event e) {
            if (cancelUpload()) {
              e.doit = false;
            }
          }
        },
        new RwtKeyStroke(SWT.CR) {
          @Override
          public void handleUiAction(Event e) {
            handleUiInputVerifier(e.doit);
          }
        }};
  }

  /*
   * scout properties
   */
  @Override
  protected void attachScout() {
    super.attachScout();
    setFileIconIdFromScout(getScoutObject().getFileIconId());
    if (getScoutObject().isFolderMode()) {
      String msg = "IFileChooserField.isFolderMode() == true is not possible in RAP";
      LOG.error(msg);
      getUiLabel().setStatus(new ProcessingStatus(msg, IProcessingStatus.ERROR));
    }
    // context menu
    updateContextMenuVisibilityFromScout();
    if (getScoutObject().getContextMenu() != null && m_contextMenuPropertyListener == null) {
      m_contextMenuPropertyListener = new P_ContextMenuPropertyListener();
      getScoutObject().getContextMenu().addPropertyChangeListener(IContextMenu.PROP_VISIBLE, m_contextMenuPropertyListener);
    }
  }

  @Override
  protected void detachScout() {
    // context menu listener
    if (m_contextMenuPropertyListener != null) {
      getScoutObject().getContextMenu().removePropertyChangeListener(IContextMenu.PROP_VISIBLE, m_contextMenuPropertyListener);
      m_contextMenuPropertyListener = null;
    }
    super.detachScout();
  }

  @Override
  protected void setDisplayTextFromScout(String s) {
//    getUiBrowseButton().setDropdownEnabled(calculateDropDownButtonEnabled());
    if (s == null) {
      s = "";
    }
    getUiField().setText(s);
    super.handleUiFocusGained();
    getUiField().setCaretOffset(0);
  }

  @Override
  protected void setEnabledFromScout(boolean b) {
    super.setEnabledFromScout(b);
    getUiBrowseButton().setButtonEnabled(b);
    //textfield must be disabled. We can't upload the file from it for now.
    getUiField().setEnabled(false);

    if (!StringUtility.hasText(m_originalVariant)) {
      m_originalVariant = (String) m_fileContainer.getData(RWT.CUSTOM_VARIANT);
    }
    String customVariant = b ? m_originalVariant : m_originalVariant + VARIANT_DISABLED_SUFFIX;
    m_fileContainer.setData(RWT.CUSTOM_VARIANT, customVariant);
  }

  @Override
  protected void setFieldEnabled(Control field, boolean enabled) {
    if (m_editableSupport == null) {
      m_editableSupport = new TextFieldEditableSupport(getUiField());
    }
    m_editableSupport.setEditable(enabled);
  }

  protected void setFileIconIdFromScout(String s) {
    m_originalVariant = s;
    m_fileContainer.setData(RWT.CUSTOM_VARIANT, s);
    getUiField().setData(RWT.CUSTOM_VARIANT, s);
    getUiBrowseButton().setData(RWT.CUSTOM_VARIANT, s);
  }

  protected void updateContextMenuVisibilityFromScout() {
    m_menuMarkerComposite.setMarkerVisible(getScoutObject().getContextMenu().isVisible());
    if (getScoutObject().getContextMenu().isVisible()) {
      if (m_uiContextMenu == null) {
        m_uiContextMenu = new RwtScoutContextMenu(getUiField().getShell(), getScoutObject().getContextMenu(), getUiEnvironment());
        if (getUiBrowseButton() != null) {
          getUiBrowseButton().setMenu(m_uiContextMenu.getUiMenu());
        }
      }
    }
    else {
      if (getUiBrowseButton() != null) {
        getUiBrowseButton().setMenu(null);
      }
      if (m_uiContextMenu != null) {
        m_uiContextMenu.dispose();
      }
      m_uiContextMenu = null;
    }
  }

  @Override
  protected void handleUiInputVerifier(boolean doit) {
    if (!doit) {
      return;
    }
    if (m_uploadedFile == null) {
      return;
    }
    // only handle if text has changed
    if (CompareUtility.equals(m_uploadedFile, getScoutObject().getDisplayText()) && getScoutObject().getErrorStatus() == null) {
      return;
    }
    final Holder<Boolean> result = new Holder<Boolean>(Boolean.class, false);
    // notify Scout
    Runnable t = new Runnable() {
      @Override
      public void run() {
        boolean b = getScoutObject().getUIFacade().setTextFromUI(m_uploadedFile.getAbsolutePath());
        result.setValue(b);
      }
    };
    JobEx job = getUiEnvironment().invokeScoutLater(t, 0);
    try {
      job.join(2345);
    }
    catch (InterruptedException e) {
      //nop
    }
    getUiEnvironment().dispatchImmediateUiJobs();
    // end notify
    return;
  }

  @Override
  protected void handleUiFocusGained() {
    super.handleUiFocusGained();
    getUiField().setSelection(0, getUiField().getText().length());
  }

  @Override
  protected void handleUiFocusLost() {
    getUiField().setSelection(0, 0);
  }

  private void handleUpload() {
    m_uploadedFile = null;
    String url = m_handler.getUploadUrl();
    if (m_uploadListener == null) {
      m_uploadListener = new P_FileUploadListener();
    }
    m_uploadListener.startUpload();
    m_handler.addUploadListener(m_uploadListener);
    createProgressBar();
    getUiBrowseButton().submit(url);
  }

  private boolean cancelUpload() {
    if (m_uploadedFile != null) {
      return false;
    }
    if (m_uploadListener != null) {
      m_handler.removeUploadListener(m_uploadListener);
      m_uploadListener.cancelUpload();
      m_uploadListener = null;
    }
    m_handler.dispose();

    DropDownFileUpload uiBrowseButton = getUiBrowseButton();
    if (uiBrowseButton != null && !uiBrowseButton.isDisposed()) {
      uiBrowseButton.dispose();
    }

    ProgressBar uiProgressBar = getUiProgressBar();
    if (uiProgressBar != null && !uiProgressBar.isDisposed()) {
      uiProgressBar.dispose();
    }
    getUiField().setText("");

    initializeFileUpload();

    createBrowseButton();

    return true;
  }

  @Override
  protected void handleScoutPropertyChange(String name, Object newValue) {
    super.handleScoutPropertyChange(name, newValue);
    if (name.equals(IFileChooserField.PROP_FILE_ICON_ID)) {
      setFileIconIdFromScout((String) newValue);
    }
  }

  private class P_FileUploadListener implements FileUploadListener {

    private final ServerPushSession m_pushSession;
    private int m_oldPercentage = 0;

    public P_FileUploadListener() {
      m_pushSession = new ServerPushSession();
    }

    public void startUpload() {
      m_pushSession.start();
    }

    public void cancelUpload() {
      m_pushSession.stop();
    }

    private int getPercentage(FileUploadEvent uploadEvent) {
      double bytesRead = uploadEvent.getBytesRead();
      double contentLength = uploadEvent.getContentLength();
      double fraction = bytesRead / contentLength;
      return (int) Math.floor(fraction * 100);
    }

    @Override
    public void uploadProgress(final FileUploadEvent uploadEvent) {
      getUiEnvironment().getDisplay().asyncExec(new Runnable() {
        @Override
        public void run() {
          int percent = getPercentage(uploadEvent);
          if (percent != m_oldPercentage && getUiProgressBar() != null && !getUiProgressBar().isDisposed()) {
            m_oldPercentage = percent;
            getUiProgressBar().setSelection(percent);
            getUiProgressBar().setToolTipText("Upload progress: " + percent + "%");
          }
        }
      });
    }

    @Override
    public void uploadFinished(final FileUploadEvent uploadEvent) {
      DiskFileUploadReceiver receiver = (DiskFileUploadReceiver) m_handler.getReceiver();
      File[] uploadedFiles = receiver.getTargetFiles();
      if (uploadedFiles != null && uploadedFiles.length > 0) {
        m_uploadedFile = uploadedFiles[0]; // only supports one file upload.
      }
      else {
        m_uploadedFile = null;
      }
      getUiEnvironment().getDisplay().asyncExec(new Runnable() {

        @Override
        public void run() {
          if (m_uploadedFile != null) {
            handleUiInputVerifier(true);
          }
        }
      });
      getUiEnvironment().getDisplay().asyncExec(new Runnable() {
        @Override
        public void run() {
          if (getUiProgressBar() != null && !getUiProgressBar().isDisposed()) {
            getUiProgressBar().dispose();
          }
          m_handler.removeUploadListener(m_uploadListener);
        }
      });
      m_pushSession.stop();
    }

    @Override
    public void uploadFailed(final FileUploadEvent uploadEvent) {
      getUiEnvironment().getDisplay().asyncExec(new Runnable() {
        @Override
        public void run() {
          if (getUiLabel() != null) {
            getUiLabel().setStatus(new ScoutFieldStatus(uploadEvent.getException().getMessage(), IStatus.ERROR));
          }
          if (getUiProgressBar() != null && !getUiProgressBar().isDisposed()) {
            getUiProgressBar().dispose();
          }
          m_handler.removeUploadListener(m_uploadListener);
        }
      });
      m_pushSession.stop();
    }
  }

  private class P_ContextMenuPropertyListener implements PropertyChangeListener {
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
      if (IContextMenu.PROP_VISIBLE.equals(evt.getPropertyName())) {
        // synchronize
        getUiEnvironment().invokeUiLater(new Runnable() {
          @Override
          public void run() {
            updateContextMenuVisibilityFromScout();
          }
        });
      }
    }
  }
}
