/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.shell.log;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.dev.BootStrapPlatform;
import com.google.gwt.dev.shell.CloseButton;
import com.google.gwt.dev.shell.CloseButton.Callback;
import com.google.gwt.dev.shell.WrapLayout;
import com.google.gwt.dev.shell.log.SwingTreeLogger.LogEvent;
import com.google.gwt.dev.util.BrowserLauncher;
import com.google.gwt.dev.util.log.AbstractTreeLogger;
import com.google.gwt.dev.util.log.CompositeTreeLogger;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.HeadlessException;
import java.awt.Point;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.UIManager;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkEvent.EventType;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.html.HTMLDocument;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

/**
 * Swing widget containing a tree logger.
 * 
 * <p>
 * This class should not be serialized.
 * </p>
 */
public class SwingLoggerPanel extends JPanel implements TreeSelectionListener,
    HyperlinkListener {

  /**
   * Callback interface for optional close button behavior.
   */
  public interface CloseHandler {
    
    /**
     * Called when the close button has been clicked on the tree logger
     * and any confirmation needed has been handled.
     * 
     * @param loggerPanel SwingTreeLogger instance being closed
     */
    void onCloseRequest(SwingLoggerPanel loggerPanel);
  }

  private class FindBox extends JPanel {

    private Popup findPopup;
    private String lastSearch;

    private ArrayList<DefaultMutableTreeNode> matches;

    private int matchNumber;
    private JTextField searchField;
    private JLabel searchStatus;

    public FindBox() {
      super(new BorderLayout());
      JPanel top = new JPanel(new FlowLayout());
      searchField = new JTextField(20);
      top.add(searchField);
      JButton nextButton = new JButton("+");
      top.add(nextButton);
      nextButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          nextMatch();
        }
      });
      JButton prevButton = new JButton("-");
      top.add(prevButton);
      prevButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          prevMatch();
        }
      });
      CloseButton closeButton = new CloseButton("Close this search box");
      closeButton.setCallback(new Callback() {
        public void onCloseRequest() {
          hideFindBox();
        }
      });
      top.add(closeButton);
      KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
      getInputMap(WHEN_IN_FOCUSED_WINDOW).put(key, "find-cancel");
      key = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
      getInputMap(WHEN_IN_FOCUSED_WINDOW).put(key, "find-search");
      getActionMap().put("find-search", new AbstractAction() {
        public void actionPerformed(ActionEvent e) {
          lastSearch = searchField.getText();
          matches = doFind(lastSearch);
          matchNumber = 0;
          updateSearchResult();
        }
      });
      AbstractAction closeFindBox = new AbstractAction() {
        public void actionPerformed(ActionEvent e) {
          hideFindBox();
        }
      };
      getActionMap().put("find-cancel", closeFindBox);
      add(top, BorderLayout.NORTH);
      searchStatus = new JLabel("Type search text and press Enter");
      searchStatus.setBorder(BorderFactory.createEmptyBorder(0, 2, 2, 0));
      add(searchStatus, BorderLayout.SOUTH);
    }

    public void hideBox() {
      if (findPopup != null) {
        findPopup.hide();
        findPopup = null;
      }
    }

    public void nextMatch() {
      if (matches != null && matches.size() > 0) {
        matchNumber = (matchNumber + 1) % matches.size();
        updateSearchResult();
      }
    }

    public void prevMatch() {
      if (matches != null) {
        int n = matches.size();
        if (n > 0) {
          matchNumber = (matchNumber + n - 1) % n;
          updateSearchResult();
        }
      }
    }

    public void showBox() {
      Point loggerOrigin = details.getLocationOnScreen();
      Dimension dim = details.getSize();
      if (findPopup != null) {
        findPopup.hide();
      }
      // have to display once to get the correct size
      int width = findBox.getWidth();
      boolean needsRelocate = (width <= 0);
      int x = loggerOrigin.x + dim.width - width;
      int y = loggerOrigin.y + dim.height - findBox.getHeight();
      PopupFactory popupFactory = PopupFactory.getSharedInstance();
      // TODO(jat): need to track window resize?
      findPopup = popupFactory.getPopup(SwingLoggerPanel.this, findBox, x, y);
      findPopup.show();
      if (needsRelocate) {
        x = loggerOrigin.x + dim.width - findBox.getWidth();
        y = loggerOrigin.y + dim.height - findBox.getHeight();
        findPopup.hide();
        findPopup = popupFactory.getPopup(SwingLoggerPanel.this, findBox, x, y);
        findPopup.show();
      }
      searchField.requestFocusInWindow();
    }

    private void updateSearchResult() {
      int n = matches.size();
      if (n == 0) {
        searchStatus.setText("No matches");
      } else {
        searchStatus.setText(String.valueOf(matchNumber + 1) + " of "
            + n + " matches");
        showFindResult(matches.get(matchNumber), lastSearch);
      }
    }
  }

  private static class TreeRenderer extends DefaultTreeCellRenderer {
    @Override
    public Component getTreeCellRendererComponent(JTree tree, Object value,
        boolean sel, boolean expanded, boolean leaf, int row,
        boolean componentHasFocus) {
      super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row,
          componentHasFocus);
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
      Object userObject = node.getUserObject();
      if (userObject instanceof LogEvent) {
        LogEvent event = (LogEvent) userObject;
        event.setDisplayProperties(this);
      }
      return this;
    }
  }

  /**
   * The mask to use for Ctrl -- mapped to Command on Mac.
   */
  private static int ctrlKeyDown;

  private static final Color DISCONNECTED_COLOR = Color.decode("0xFFDDDD");

  static {
    ctrlKeyDown = BootStrapPlatform.isMac() ?  InputEvent.ALT_DOWN_MASK
        : InputEvent.CTRL_DOWN_MASK;
  }

  // package protected for SwingTreeLogger to access
  Type levelFilter;

  String regexFilter;

  private final JTree tree;

  DefaultTreeModel treeModel;

  private CloseHandler closeHandler;

  private CloseButton closeLogger;

  private final JEditorPane details;

  private boolean disconnected = false;

  private FindBox findBox;

  private JComboBox levelComboBox;

  private final TreeLogger logger;

  private JTextField regexField;
  
  private DefaultMutableTreeNode root;

  private JPanel topPanel;
  
  private JScrollPane treeView;

  private JCheckBox autoScroll;

  /**
   * Create a Swing-based logger panel, with a tree section and a detail
   * section.
   * 
   * @param maxLevel
   * @param logFile
   */
  public SwingLoggerPanel(TreeLogger.Type maxLevel, File logFile) {
    super(new BorderLayout());
    regexFilter = "";
    levelFilter = maxLevel;
    // TODO(jat): how to make the topPanel properly layout items
    // when the window is resized
    topPanel = new JPanel(new BorderLayout());
    JPanel logButtons = new JPanel(new WrapLayout());
    JButton expandButton = new JButton("Expand All");
    expandButton.setMnemonic(KeyEvent.VK_E);
    expandButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        expandAll();
      }
    });
    logButtons.add(expandButton);
    JButton collapseButton = new JButton("Collapse All");
    collapseButton.setMnemonic(KeyEvent.VK_O);
    collapseButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        collapseAll();
      }
    });
    logButtons.add(collapseButton);
    autoScroll = new JCheckBox("Auto-scroll", true);
    autoScroll.setMnemonic(KeyEvent.VK_U);
    logButtons.add(autoScroll);
    topPanel.add(logButtons, BorderLayout.CENTER);
    // TODO(jat): temporarily avoid showing parts that aren't implemented.
    if (false) {
      logButtons.add(new JLabel("Filter Log Messages: "));
      levelComboBox = new JComboBox();
      for (TreeLogger.Type type : TreeLogger.Type.instances()) {
        if (type.compareTo(maxLevel) > 0) {
          break;
        }
        levelComboBox.addItem(type);
      }
      levelComboBox.setEditable(false);
      levelComboBox.setSelectedIndex(levelComboBox.getItemCount() - 1);
      topPanel.add(levelComboBox);
      levelComboBox.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          setLevelFilter((TreeLogger.Type) levelComboBox.getSelectedItem());
        }
      });
      regexField = new JTextField(20);
      logButtons.add(regexField);
      JButton applyRegexButton = new JButton("Apply Regex");
      applyRegexButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          setRegexFilter(regexField.getText());
        }
      });
      logButtons.add(applyRegexButton);
      JButton clearRegexButton = new JButton("Clear Regex");
      clearRegexButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          regexField.setText("");
          setRegexFilter("");
        }
      });
      logButtons.add(clearRegexButton);
    }
    closeLogger = new CloseButton("Close this log window");
    closeLogger.setCallback(new Callback() {
      // TODO(jat): add support for closing active session when SWT is removed
      public void onCloseRequest() {
        if (disconnected && closeHandler != null) {
          closeHandler.onCloseRequest(SwingLoggerPanel.this);
        }
      }
    });
    closeLogger.setEnabled(false);
    closeLogger.setVisible(false);
    topPanel.add(closeLogger, BorderLayout.EAST);
    add(topPanel, BorderLayout.NORTH);
    root = new DefaultMutableTreeNode();
    treeModel = new DefaultTreeModel(root);
    treeModel.addTreeModelListener(new TreeModelListener() {
      @Override public void treeNodesInserted(TreeModelEvent e) {
        for (Object treeNode : e.getChildren()) {
          onTreeNodeAdded((DefaultMutableTreeNode) treeNode);
        }
      }
      @Override public void treeStructureChanged(TreeModelEvent e) { }
      @Override public void treeNodesRemoved(TreeModelEvent e) { }
      @Override public void treeNodesChanged(TreeModelEvent e) { }
    });
    tree = new JTree(treeModel);
    tree.setRootVisible(false);
    tree.setEditable(false);
    tree.setExpandsSelectedPaths(true);
    tree.setShowsRootHandles(true);
    tree.setCellRenderer(new TreeRenderer());
    tree.getSelectionModel().setSelectionMode(
        TreeSelectionModel.SINGLE_TREE_SELECTION);
    tree.addTreeSelectionListener(this);
    treeView = new JScrollPane(tree);
    // TODO(jat): better way to do this
    details = new JEditorPane() {
      @Override
      public boolean getScrollableTracksViewportWidth() {
        return true;
      }
    };
    details.setEditable(false);
    details.setContentType("text/html");
    details.setForeground(Color.BLACK);
    details.addHyperlinkListener(this);
    // font trick from http://explodingpixels.wordpress.com/2008/10/28/make-jeditorpane-use-the-system-font/
    Font font = UIManager.getFont("Label.font");
    String bodyRule = "body { font-family: " + font.getFamily() + "; "
        + "font-size: " + font.getSize() + "pt; }";
    ((HTMLDocument) details.getDocument()).getStyleSheet().addRule(bodyRule);
    JScrollPane msgView = new JScrollPane(details);
    JSplitPane splitter = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
    splitter.setTopComponent(treeView);
    splitter.setBottomComponent(msgView);
    Dimension minSize = new Dimension(100, 50);
    msgView.setMinimumSize(minSize);
    treeView.setMinimumSize(minSize);
    splitter.setDividerLocation(0.80);
    add(splitter);
    
    AbstractTreeLogger uiLogger = new SwingTreeLogger(this);
    uiLogger.setMaxDetail(maxLevel);
    TreeLogger bestLogger = uiLogger;
    if (logFile != null) {
      try {
        PrintWriterTreeLogger fileLogger = new PrintWriterTreeLogger(logFile);
        fileLogger.setMaxDetail(maxLevel);
        bestLogger = new CompositeTreeLogger(bestLogger, fileLogger);
      } catch (IOException ex) {
        bestLogger.log(TreeLogger.ERROR, "Can't log to file "
            + logFile.getAbsolutePath(), ex);
      }
    }
    logger = bestLogger;
    KeyStroke key = getCommandKeyStroke(KeyEvent.VK_F, false);
    getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(key, "find");
    getActionMap().put("find", new AbstractAction() {
      public void actionPerformed(ActionEvent e) {
        showFindBox();
      }
    });
    key = getCommandKeyStroke(KeyEvent.VK_C, false);
    tree.getInputMap().put(key, "copy");
    tree.getActionMap().put("copy", new AbstractAction() {
      public void actionPerformed(ActionEvent e) {
        treeCopy();
      }
    });
    findBox = new FindBox();
    key = getCommandKeyStroke(KeyEvent.VK_G, false);
    tree.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(key, "findnext");
    tree.getActionMap().put("findnext", new AbstractAction() {
      public void actionPerformed(ActionEvent e) {
        findBox.nextMatch();
      }
    });
    key = getCommandKeyStroke(KeyEvent.VK_G, true);
    tree.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(key, "findprev");
    tree.getActionMap().put("findprev", new AbstractAction() {
      public void actionPerformed(ActionEvent e) {
        findBox.prevMatch();
      }
    });
  }

  /**
   * Collapse all tree nodes.
   */
  @SuppressWarnings("unchecked")
  public void collapseAll() {
    Enumeration<DefaultMutableTreeNode> children = root.postorderEnumeration();
    while (children.hasMoreElements()) {
      DefaultMutableTreeNode node = children.nextElement();
      if (node != root) {
        tree.collapsePath(new TreePath(node.getPath()));
      }
    }
    tree.invalidate();
  }

  /**
   * Show that the client connected to this logger has disconnected.
   */
  public void disconnected() {
    disconnected  = true;
    tree.setBackground(DISCONNECTED_COLOR);
    tree.repaint();
  }

  /**
   * Expand all tree nodes.
   */
  @SuppressWarnings("unchecked")
  public void expandAll() {
    Enumeration<DefaultMutableTreeNode> children = root.postorderEnumeration();
    while (children.hasMoreElements()) {
      DefaultMutableTreeNode node = children.nextElement();
      if (node != root) {
        tree.expandPath(new TreePath(node.getPath()));
      }
    }
    tree.invalidate();
  }

  /**
   * @return the TreeLogger for this panel
   */
  public TreeLogger getLogger() {
    return logger;
  }

  public void hyperlinkUpdate(HyperlinkEvent event) {
    EventType eventType = event.getEventType();
    if (eventType == HyperlinkEvent.EventType.ACTIVATED) {
      URL url = event.getURL();
      try {
        BrowserLauncher.browse(url.toExternalForm());
        return;
      } catch (Exception e) {
        // if anything fails, fall-through to failsafe implementation
      }
      // As a last resort, just use the details pane to display the HTML, but
      // this is rather poor.
      try {
        details.setPage(url);
      } catch (IOException e) {
        logger.log(TreeLogger.ERROR, "Unable to follow link to " + url, e);
      }
    }
  }

  @Override
  public void removeAll() {
    tree.removeAll();
    details.setText("");
  }

  /**
   * Sets a callback for handling a close request, which also makes the close
   * button visible.
   * 
   * @param handler
   */
  public void setCloseHandler(CloseHandler handler) {
    closeHandler = handler;
    closeLogger.setEnabled(true);
    closeLogger.setVisible(true);
  }

  public void valueChanged(TreeSelectionEvent e) {
    if (e.isAddedPath()) {
      TreePath path = e.getPath();
      Object treeNode = path.getLastPathComponent();
      if (treeNode == null) {
        // handle the case of no selection
        details.setText("");
        return;
      }
      Object userObject = ((DefaultMutableTreeNode) treeNode).getUserObject();
      String text = userObject.toString();
      if (userObject instanceof LogEvent) {
        LogEvent event = (LogEvent) userObject;
        text = event.getFullText();
      }
      details.setText(text);
    }
  }

  protected void alert(String msg) {
    JOptionPane.showMessageDialog(null, msg, "Alert: Not Implemented",
        JOptionPane.INFORMATION_MESSAGE);
  }

  /**
   * Ask the user for confirmation to close the current logger.
   * 
   * @return true if the user confirmed the request
   */
  protected boolean confirmClose() {
    int response = JOptionPane.showConfirmDialog(null,
        "Close the logger for the currently displayed module",
        "Close this Logger", JOptionPane.OK_CANCEL_OPTION,
        JOptionPane.WARNING_MESSAGE);
    return response != JOptionPane.YES_OPTION;
  }

  protected ArrayList<DefaultMutableTreeNode> doFind(String search) {
    @SuppressWarnings("unchecked")
    Enumeration<DefaultMutableTreeNode> children = root.preorderEnumeration();
    ArrayList<DefaultMutableTreeNode> matches = new ArrayList<DefaultMutableTreeNode>();
    while (children.hasMoreElements()) {
      DefaultMutableTreeNode node = children.nextElement();
      if (node != root && nodeMatches(node, search)) {
        matches.add(node);
        // Make sure our this entry is visible by expanding up to parent
        TreeNode[] nodePath = node.getPath();
        if (nodePath.length > 1) {
          TreeNode[] parentPath = new TreeNode[nodePath.length - 1];
          System.arraycopy(nodePath, 0, parentPath, 0, parentPath.length);
          tree.expandPath(new TreePath(parentPath));
        }
      }
    }
    tree.invalidate();
    return matches;
  }

  protected void hideFindBox() {
    findBox.hideBox();
  }

  protected void setLevelFilter(Type selectedLevel) {
    levelFilter = selectedLevel;
    // TODO(jat): filter current tree
    alert("Filtering not implemented yet");
  }

  protected void setRegexFilter(String regex) {
    regexFilter = regex;
    // TODO(jat): filter current tree
    alert("Regex filtering not implemented yet");
  }

  protected void showFindBox() {
    findBox.showBox();
  }

  protected void treeCopy() {
    DefaultMutableTreeNode node = (DefaultMutableTreeNode)
        tree.getLastSelectedPathComponent();
    if (node == null) {
      return;
    }
    // is it better to use SwingUtilities2.canAccessSystemClipboard() here? 
    Clipboard clipboard;
    try {
      clipboard = tree.getToolkit().getSystemClipboard();
    } catch (SecurityException e) {
      return;
    } catch (HeadlessException e) {
      return;
    }
    if (clipboard == null) {
      return;
    }
    StringBuilder text = new StringBuilder();
    treeLogTraverse(text, node, 0);
    StringSelection selection = new StringSelection(text.toString());
    clipboard.setContents(selection, selection);
  }

  /**
   * Returns a keystroke which adds the appropriate modifier for a command key:
   * Command on mac, Ctrl everywhere else.
   * 
   * @param key virtual key defined in {@code KeyEvent#VK_*}
   * @param shift true if the Ctrl/Command key must be shifted
   * @return KeyStroke of the Ctrl/Command-key
   */
  private KeyStroke getCommandKeyStroke(int key, boolean shift) {
    int mask = ctrlKeyDown;
    if (shift) {
      mask |= InputEvent.SHIFT_DOWN_MASK;
    }
    return KeyStroke.getKeyStroke(key, mask);
  }

  private String htmlUnescape(String str) {
    // TODO(jat): real implementation, needs to correspond to
    // SwingTreeLogger.htmlEscape()
    return str.replace("&lt;", "<").replace("&gt;", ">").replace("&amp;",
        "&").replace("<br>", "\n");
  }

  private boolean nodeMatches(DefaultMutableTreeNode node, String search) {
    Object userObject = node.getUserObject();
    if (userObject instanceof LogEvent) {
      LogEvent event = (LogEvent) userObject;
      String text = htmlUnescape(event.getFullText());
      // TODO(jat): should this be more than a substring match, such as regex?
      if (text.contains(search)) {
        return true;
      }
    }
    return false;
  }

  /**
   * @param search the search string, currently ignored.
   */
  private void showFindResult(DefaultMutableTreeNode node, String search) {
    // TODO(jat): highlight search string
    TreePath path = new TreePath(node.getPath());
    tree.scrollPathToVisible(path);
    tree.setSelectionPath(path);
  }

  private void treeLogTraverse(StringBuilder buf, TreeNode node,
      int indent) {
    for (int i = 0; i < indent; ++i) {
      buf.append(' ');
    }
    if (node instanceof DefaultMutableTreeNode) {
      DefaultMutableTreeNode mutableNode = (DefaultMutableTreeNode) node;
      Object userObject = mutableNode.getUserObject();
      if (userObject instanceof LogEvent) {
        LogEvent event = (LogEvent) userObject;
        buf.append(htmlUnescape(event.getFullText()));
        if (event.isBranchCommit) {
          SwingTreeLogger childLogger = event.childLogger;
          DefaultMutableTreeNode parent = childLogger.treeNode;
          for (int i = 0; i < parent.getChildCount(); ++i) {
            treeLogTraverse(buf, parent.getChildAt(i), indent + 2);
          }
        }
      } else {
        buf.append(userObject.toString());
        buf.append('\n');
      }
    } else {
      buf.append(node.toString());
      buf.append('\n');
    }
  }

  private void onTreeNodeAdded(DefaultMutableTreeNode treeNode) {
    TreePath path = new TreePath(treeNode.getPath());
    if (autoScroll.isSelected()) {
      tree.scrollPathToVisible(path); // internally will also call makeVisible
    } else {
      Object userObject = treeNode.getUserObject();
      if (userObject instanceof LogEvent) {
        if (((LogEvent) userObject).type.needsAttention()) {
          tree.makeVisible(path);
        }
      }
    }
  }
}
