/*
 * Copyright (c) 2012 Google Inc.
 *
 * 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
 */
package com.google.eclipse.elt.view.ui;

import com.google.eclipse.elt.emulator.control.ITerminalListener;
import com.google.eclipse.elt.emulator.provisional.api.TerminalState;
import com.google.eclipse.elt.view.Activator;
import com.google.eclipse.elt.view.ImageKeys;
import com.google.eclipse.elt.view.connector.LifeCycleListener;
import com.google.eclipse.elt.view.preferences.AbstractPreferencesChangeListener;
import com.google.eclipse.elt.view.preferences.ColorsAndFontsPreferences;
import com.google.eclipse.elt.view.preferences.GeneralPreferences;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.ISaveablePart2;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.contexts.IContextActivation;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.UIJob;

import java.io.File;
import java.util.UUID;

/**
 * @author alruiz@google.com (Alex Ruiz)
 */
public class TerminalView extends ViewPart implements ISaveablePart2 {
  private static final String SCROLL_LOCK_ENABLED = "scrollLock";
  private static final String TITLE_STATE_TYPE = "title";
  private static final String WORKING_DIRECTORY_STATE_TYPE = "workingDirectory";

  private static final String VIEW_ID = "com.google.eclipse.terminal.local.localTerminalView";

  private IPropertyChangeListener preferencesChangeListener;
  private IPropertyChangeListener textFontChangeListener;
  private IMemento savedState;
  private TerminalWidget terminalWidget;
  private IPath workingDirectory;

  private Action newTerminalAction;
  private Action scrollLockAction;

  private boolean checkCanBeClosed;
  private boolean forceClose;

  private IContextActivation contextActivation;

  /**
   * Creates a new terminal view.
   *
   * @param workingDirectory the working directory to be opened on initialization
   */
  public static void openTerminalView(IPath workingDirectory) {
    openNewTerminalView(workingDirectory);
  }

  /**
   * Opens a new {@link TerminalView}.
   *
   * @param workingDirectory the working directory to be opened on initialization
   */
  private static void openNewTerminalView(IPath workingDirectory) {
    IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
    IPath safeWorkingDirectory =
        (workingDirectory != null) ? workingDirectory : getDefaultWorkingDirectory();
    try {
      String directoryName = safeWorkingDirectory.lastSegment();
      // Use of a freshTerminalId to force freshness of the identifier.
      String secondaryId = UUID.randomUUID().toString();
      TerminalView view =
          (TerminalView) page.showView(VIEW_ID, secondaryId, IWorkbenchPage.VIEW_ACTIVATE);
      view.setPartName(directoryName);
      view.open(safeWorkingDirectory);
    } catch (PartInitException e) {
      Activator.log("Unable to create Terminal View", e);
    }
  }

  @Override public void init(IViewSite site, IMemento memento) throws PartInitException {
    super.init(site, memento);
    savedState = memento;
  }

  @Override public void saveState(IMemento memento) {
    saveState(memento, SCROLL_LOCK_ENABLED, String.valueOf(terminalWidget.isScrollLockEnabled()));
    saveState(memento, TITLE_STATE_TYPE, getPartName());
    if (workingDirectory != null) {      
      saveState(memento, WORKING_DIRECTORY_STATE_TYPE, workingDirectory.toOSString());
    }
  }

  private void saveState(IMemento memento, String type, String data) {
    IMemento child = memento.createChild(type);
    child.putTextData(data);
  }
  
  /**
   * Returns a non-{@code null} directory to be used as the default working directory if one isn't
   * explicitly provided.
   */
  private static IPath getDefaultWorkingDirectory() {
    File homeDirectory = new File(System.getProperty("user.home"));
    if (homeDirectory.isDirectory()) {
      return Path.fromOSString(homeDirectory.getAbsolutePath());
    }
    File currentDirectory = new File(System.getProperty("user.dir"));
    if (currentDirectory.isDirectory()) {
      return Path.fromOSString(currentDirectory.getAbsolutePath());
    }
    // If all else fails, pick the first root we can find.
    for (File root : File.listRoots()) {
     if (root.isDirectory()) {
       return Path.fromOSString(root.getAbsolutePath());
     }
    }
    throw new IllegalStateException("Could not find valid working directory.");
  }

  @Override public void createPartControl(Composite parent) {
    terminalWidget = new TerminalWidget(parent, getViewSite());
    terminalWidget.setLifeCycleListener(new LifeCycleListener() {
      @Override public void executionFinished() {
        closeViewOnExitIfPossible();
      }
    });
    terminalWidget.setTerminalListener(new ITerminalListener() {
      @Override public void setTerminalTitle(final String title) {
        updatePartName(title);
      }

      @Override public void setState(TerminalState state) {}
    });
    IViewSite viewSite = getViewSite();
    preferencesChangeListener = new AbstractPreferencesChangeListener() {
      @Override protected void onBufferLineCountChanged() {
        updateBufferLineCount();
      }

      @Override protected void onColorChanged() {
        updateColors();
      }

      @Override protected void onFontChanged() {
        updateFont();
      }

      @Override protected void onUseBlinkingCursorChanged() {
        updateUsageOfBlinkingCursor();
      }
    };
    Activator.preferenceStore().addPropertyChangeListener(preferencesChangeListener);
    updateBufferLineCount();
    updateColors();
    updateUsageOfBlinkingCursor();
    textFontChangeListener = new IPropertyChangeListener() {
      @Override public void propertyChange(PropertyChangeEvent event) {
        if (JFaceResources.TEXT_FONT.equals(event.getProperty())) {
          if (!ColorsAndFontsPreferences.useCustomFont()) {
            setFont(JFaceResources.getTextFont());
          }
        }
      }
    };
    JFaceResources.getFontRegistry().addListener(textFontChangeListener);
    updateFont();
    setupToolBarActions();
    IContextService contextService = contextService();
    if (contextService != null) {
      contextActivation =
          contextService.activateContext("com.google.eclipse.terminal.local.context.localTerminal");
    }
    if (savedState != null) {
      updateScrollLockUsingSavedState();
      connectUsingSavedState();
      return;
    }
    if (viewSite.getSecondaryId() == null) {
      setPartName(Messages.defaultViewTitle);
      open(getDefaultWorkingDirectory());
    }
    enableScrollLock(scrollLockAction.isChecked());
  }

  private void closeViewOnExitIfPossible() {
    if (GeneralPreferences.closeViewOnExit() && terminalWidget != null
        && !terminalWidget.isDisposed()) {
      // must run in UI thread.
      forceClose = true;
      terminalWidget.getDisplay().asyncExec(new Runnable() {
        @Override public void run() {
          IWorkbenchPartSite site = getSite();
          site.getPage().hideView((IViewPart) site.getPart());
        }
      });
    }
  }

  private void updateColors() {
    terminalWidget.setColors(ColorsAndFontsPreferences.background(),
        ColorsAndFontsPreferences.foreground());
  }

  private void updateFont() {
    setFont(terminalFont());
  }

  private void updateUsageOfBlinkingCursor() {
    terminalWidget.setBlinkingCursor(ColorsAndFontsPreferences.useBlinkingCursor());
  }

  private Font terminalFont() {
    if (ColorsAndFontsPreferences.useCustomFont()) {
      return new Font(Display.getDefault(), ColorsAndFontsPreferences.customFontData());
    }
    return JFaceResources.getTextFont();
  }

  private void setFont(Font font) {
    terminalWidget.setFont(font);
  }

  private void updateBufferLineCount() {
    terminalWidget.setBufferLineCount(GeneralPreferences.bufferLineCount());
  }

  private void setupToolBarActions() {
    IToolBarManager toolBarManager = getViewSite().getActionBars().getToolBarManager();
    toolBarManager.add(new ChangeViewNameAction());
    toolBarManager.add(new Separator());
    newTerminalAction = new NewTerminalAction();
    toolBarManager.add(newTerminalAction);
    scrollLockAction = new ScrollLockAction();
    toolBarManager.add(scrollLockAction);
  }

  private void updateScrollLockUsingSavedState() {
    boolean newValue = Boolean.valueOf(savedState(SCROLL_LOCK_ENABLED));
    enableScrollLockAndUpdateAction(newValue);
  }

  private void enableScrollLockAndUpdateAction(boolean enabled) {
    enableScrollLock(enabled);
    scrollLockAction.setChecked(enabled);
  }

  private void enableScrollLock(boolean enabled) {
    terminalWidget.enableScrollLock(enabled);
  }

  private void connectUsingSavedState() {
    String title = savedState(TITLE_STATE_TYPE);
    setPartName(title);
    String savedWorkingDirectory = savedState(WORKING_DIRECTORY_STATE_TYPE);
    if (savedWorkingDirectory == null) {
      open(getDefaultWorkingDirectory());
    } else {      
      open(Path.fromOSString(savedWorkingDirectory));
    }
  }

  private String savedState(String type) {
    IMemento child = savedState.getChild(type);
    return (child != null) ? child.getTextData() : null;
  }

  private void open(IPath workingDirectory) {
    // workingDirectory should be non-null.
    if (terminalWidget.isConnected()) {
      return;
    }
    this.workingDirectory = workingDirectory;
    terminalWidget.setWorkingDirectory(workingDirectory);
    terminalWidget.connect();
  }

  private void updatePartName(final String value) {
    UIJob job = new UIJob("Update terminal view title") {
      @Override public IStatus runInUIThread(IProgressMonitor monitor) {
        setPartName(value);
        return Status.OK_STATUS;
      }
    };
    job.schedule();
  }

  @Override public void setFocus() {
    terminalWidget.setFocus();
  }

  @Override public void dispose() {
    if (contextActivation != null) {
      IContextService contextService = contextService();
      if (contextService != null) {
        contextService.deactivateContext(contextActivation);
      }
    }
    if (preferencesChangeListener != null) {
      Activator.preferenceStore().removePropertyChangeListener(preferencesChangeListener);
    }
    if (textFontChangeListener != null) {
      JFaceResources.getFontRegistry().removeListener(textFontChangeListener);
    }
    super.dispose();
  }

  private IContextService contextService() {
    return (IContextService) getSite().getService(IContextService.class);
  }

  @Override public boolean isDirty() {
    if (checkCanBeClosed) {
      checkCanBeClosed = false;
      return true;
    }
    return false;
  }

  @Override public boolean isSaveOnCloseNeeded() {
    if (forceClose) {
      return false;
    }
    checkCanBeClosed = true;
    return true;
  }

  @Override public int promptToSaveOnClose() {
    if (GeneralPreferences.warnOnClose()) {
      boolean close = WarnOnCloseDialog.open(terminalWidget.getShell());
      if (!close) {
        return CANCEL;
      }
    }
    return NO;
  }

  @Override public void doSave(IProgressMonitor monitor) {}

  @Override public void doSaveAs() {}

  @Override public boolean isSaveAsAllowed() {
    return false;
  }

  private class NewTerminalAction extends Action {
    NewTerminalAction() {
      setImageDescriptor(Activator.imageDescriptor(ImageKeys.NEW_TERMINAL));
      setText(Messages.newLocalTerminal);
    }

    @Override public void run() {
      openNewTerminalView(workingDirectory);
    }
  }

  private class ScrollLockAction extends Action {
    ScrollLockAction() {
      super(Messages.scrollLock, AS_RADIO_BUTTON);
      setChecked(false);
      setImageDescriptor(Activator.imageDescriptor(ImageKeys.SCROLL_LOCK));
    }

    @Override public void run() {
      boolean newValue = !terminalWidget.isScrollLockEnabled();
      enableScrollLockAndUpdateAction(newValue);
    }
  }

  private class ChangeViewNameAction extends Action {
    ChangeViewNameAction() {
      setImageDescriptor(Activator.imageDescriptor(ImageKeys.CHANGE_TITLE));
      setText(Messages.changeTerminalTitle);
    }

    @Override public void run() {
      Shell shell = getViewSite().getShell();
      final String currentTitle = getPartName();
      InputDialog input = new InputDialog(shell, Messages.enterTerminalTitleDialogTitle,
          Messages.enterTerminalTitlePrompt, currentTitle,
          new IInputValidator() {
            @Override public String isValid(String newText) {
              if (newText == null || newText.isEmpty() || currentTitle.equals(newText)) {
                return "";
              }
              return null;
            }
          });
      input.setBlockOnOpen(true);
      if (input.open() == Window.OK) {
        setPartName(input.getValue());
      }
    }
  }
}
