/*
 * Copyright 2009 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;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.dev.DevModeBase.HostedModeBaseOptions;
import com.google.gwt.dev.WebServerPanel.RestartAction;
import com.google.gwt.dev.shell.ShellMainWindow;
import com.google.gwt.dev.ui.DevModeUI;
import com.google.gwt.dev.ui.DoneCallback;
import com.google.gwt.dev.ui.DoneEvent;
import com.google.gwt.dev.ui.RestartServerCallback;
import com.google.gwt.dev.ui.RestartServerEvent;
import com.google.gwt.dev.util.collect.HashMap;

import java.awt.EventQueue;
import java.awt.Image;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;
import javax.swing.WindowConstants;

/**
 * Implements the Swing UI for development mode.
 */
public class SwingUI extends DevModeUI {

  /**
   * Module handle for Swing UI.
   */
  protected class SwingModuleHandle implements ModuleHandle {

    private final ModulePanel tab;

    /**
     * Create an immutable module handle.
     * @param tab the module panel associated with this instance
     */
    public SwingModuleHandle(ModulePanel tab) {
      this.tab = tab;
    }

    public TreeLogger getLogger() {
      return tab.getLogger();
    }
    
    /**
     * @return the ModulePanel associated with this module instance.
     */
    public ModulePanel getTab() {
      return tab;
    }

    public void unload() {
      if (tab != null) {
        tab.disconnect();
      }
    }
  }

  /**
   * Interface to group activities related to adding and deleting tabs.
   */
  protected interface TabPanelCollection {
    
    /**
     * Add a new tab containing a ModuleTabPanel.
     * 
     * @param tabPanel
     * @param icon
     * @param title
     * @param tooltip
     */
    void addTab(ModuleTabPanel tabPanel, ImageIcon icon, String title,
        String tooltip);
    
    /**
     * Remove the tab containing a ModuleTabpanel.
     * 
     * @param tabPanel
     */
    void removeTab(ModuleTabPanel tabPanel);
  }

  protected static final String PACKAGE_PATH = SwingUI.class.getPackage(
      ).getName().replace('.', '/').concat("/shell/");

  private static final Object sessionCounterLock = new Object();

  private static int sessionCounter = 0;

  /**
   * Loads an image from the classpath in this package.
   */
  static ImageIcon loadImageIcon(String name) {
    return loadImageIcon(name, true);
  }

  /**
   * Loads an image from the classpath, optionally prepending this package.
   * 
   * @param name name of an image file.
   * @param prependPackage true if {@link #PACKAGE_PATH} should be prepended to
   *     this name.
   * @return an ImageIcon instance to use -- in the event of an error loading
   *     the requested image, a blank ImageIcon is returned
   */
  static ImageIcon loadImageIcon(String name, boolean prependPackage) {
    ClassLoader cl = SwingUI.class.getClassLoader();
    if (prependPackage) {
      name = PACKAGE_PATH + name;
    }
    
    URL url = (name == null) ? null : cl.getResource(name);
    if (url != null) {
      ImageIcon image = new ImageIcon(url);
      return image;
    } else {
      // Bad image.
      return new ImageIcon();
    }
  }

  private final HostedModeBaseOptions options;
  private final Map<DevelModeTabKey, ModuleTabPanel> tabPanels = new HashMap<
      DevelModeTabKey, ModuleTabPanel>();

  private ShellMainWindow mainWnd;
  private JFrame frame;
  private JTabbedPane tabs;
  private WebServerPanel webServerLog;

  private TreeLogger topLogger;

  /**
   * Create a Swing UI instance.
   * 
   * @param options parsed command-line options
   */
  public SwingUI(HostedModeBaseOptions options) {
    this.options = options;
  }

  @Override
  public ModuleHandle getModuleLogger(final String userAgent,
      final String remoteSocket, final String url, final String tabKey,
      final String moduleName, final String sessionKey, final String agentTag,
      final byte[] agentIcon, final TreeLogger.Type logLevel) {
    // TODO(jat): add support for closing an active module
    ModuleHandle handle = invokeAndGet(new Callable<ModuleHandle>() {
          public ModuleHandle call() throws Exception {
            ModuleTabPanel tabPanel = findModuleTab(userAgent, remoteSocket,
                url, tabKey, moduleName, agentIcon);
            ModulePanel tab = tabPanel.addModuleSession(logLevel, moduleName,
                sessionKey, options.getLogFile(String.format("%s-%s-%d.log",
                    moduleName, agentTag, getNextSessionCounter(
                        options.getLogDir()))));
            // TODO: Switch to a wait cursor?
            return new SwingModuleHandle(tab);
          }
        });
    TreeLogger logger = handle.getLogger();
    TreeLogger branch = logger.branch(TreeLogger.INFO, "Loading module "
        + moduleName);
    if (logger.isLoggable(TreeLogger.INFO)) {
      if (url != null) {
        branch.log(TreeLogger.INFO, "Top URL: " + url);
      }
      branch.log(TreeLogger.INFO, "User agent: " + userAgent);
    }
    if (logger.isLoggable(TreeLogger.TRACE)) {
      branch.log(TreeLogger.TRACE, "Remote socket: " + remoteSocket);
    }
    if (branch.isLoggable(TreeLogger.DEBUG)) {
      if (tabKey != null) {
        branch.log(TreeLogger.DEBUG, "Tab key: " + tabKey);
      }
      if (sessionKey != null) {
        branch.log(TreeLogger.DEBUG, "Session key: " + sessionKey);
      }
    }
    return handle;
  }

  @Override
  public TreeLogger getTopLogger() {
    return topLogger;
  }

  @Override
  public TreeLogger getWebServerLogger(String serverName, byte[] serverIcon) {
    if (webServerLog == null) {
      RestartAction restartAction = null;
      final RestartServerCallback callback = getCallback(
          RestartServerEvent.getType());
      if (callback != null) {
        restartAction = new RestartAction() {
          public void restartServer(TreeLogger logger) {
            callback.onRestartServer(logger);
          }
        };
      }
      webServerLog = new WebServerPanel(options.getPort(), getLogLevel(),
          options.getLogFile("webserver.log"), restartAction);
      Icon serverIconImage = null;
      if (serverIcon != null) {
        serverIconImage = new ImageIcon(serverIcon);
      }
      tabs.insertTab(serverName, serverIconImage, webServerLog, null, 1);
    }
    return webServerLog.getLogger();
  }

  @Override
  public void initialize(final Type logLevel) {
    super.initialize(logLevel);
    invokeAndWait(new Runnable() {
      public void run() {
        ImageIcon gwtIcon16 = loadImageIcon("icon16.png");
        ImageIcon gwtIcon24 = loadImageIcon("icon24.png");
        ImageIcon gwtIcon32 = loadImageIcon("icon32.png");
        ImageIcon gwtIcon48 = loadImageIcon("icon48.png");
        ImageIcon gwtIcon64 = loadImageIcon("icon64.png");
        ImageIcon gwtIcon128 = loadImageIcon("icon128.png");
        frame = new JFrame("GWT Development Mode");
        tabs = new JTabbedPane();
        if (options.alsoLogToFile()) {
          options.getLogDir().mkdirs();
        }
        mainWnd = new ShellMainWindow(logLevel, options.getLogFile("main.log"));
        topLogger = mainWnd.getLogger();
        tabs.addTab("Development Mode", gwtIcon24, mainWnd,
            "GWT Development Mode");
        frame.getContentPane().add(tabs);
        frame.setSize(950, 700);
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        frame.addWindowListener(new WindowAdapter() {
          @Override
          public void windowClosed(WindowEvent e) {
            DoneCallback callback = getCallback(DoneEvent.getType());
            if (callback != null) {
              callback.onDone();
            }
          }
        });
        setIconImages(topLogger, gwtIcon48, gwtIcon32, gwtIcon64, gwtIcon128,
            gwtIcon16);
        frame.setVisible(true);
      }
    });
    maybeInitializeOsXApplication();
  }

  @Override
  public void moduleLoadComplete(final boolean success) {
    EventQueue.invokeLater(new Runnable() {
      public void run() {
        mainWnd.moduleLoadComplete(success);
      }
    });
  }

  @Override
  public void setStartupUrls(final Map<String, URL> urls) {
    invokeAndWait(new Runnable() {
      public void run() {
        mainWnd.setStartupUrls(urls);
      }
    });
  }

  @Override
  public void setWebServerSecure(TreeLogger serverLogger) {
    if (webServerLog != null && serverLogger == webServerLog.getLogger()) {
      EventQueue.invokeLater(new Runnable() {
        public void run() {
          // TODO(jat): if the web server has an icon, should combine with the
          // secure icon or perhaps switch to a different one.
          ImageIcon secureIcon = loadImageIcon("secure24.png");
          tabs.setIconAt(1, secureIcon);
        }
      });
    }
  }
  
  protected int getNextSessionCounter(File logdir) {
    synchronized (sessionCounterLock) {
      if (sessionCounter == 0 && logdir != null) {
        // first time only, figure out the "last" session count already in use
        for (String filename : logdir.list()) {
          if (filename.matches("^[A-Za-z0-9_$]*-[a-z]*-[0-9]*.log$")) {
            String substring = filename.substring(filename.lastIndexOf('-') + 1,
                filename.length() - 4);
            int number = Integer.parseInt(substring);
            if (number > sessionCounter) {
              sessionCounter = number;
            }
          }
        }
      }
      // 
      return ++sessionCounter;
    }
  }

  private ModuleTabPanel findModuleTab(String userAgent, String remoteSocket,
      String url, String tabKey, String moduleName, byte[] agentIcon) {
    int hostEnd = remoteSocket.indexOf(':');
    if (hostEnd < 0) {
      hostEnd = remoteSocket.length();
    }
    String remoteHost = remoteSocket.substring(0, hostEnd);
    final DevelModeTabKey key = new DevelModeTabKey(userAgent, url, tabKey,
        remoteHost);
    ModuleTabPanel moduleTabPanel = tabPanels.get(key);
    if (moduleTabPanel == null) {
      moduleTabPanel = new ModuleTabPanel(userAgent, remoteSocket, url,
          agentIcon, new TabPanelCollection() {
            public void addTab(ModuleTabPanel tabPanel, ImageIcon icon,
                String title, String tooltip) {
              synchronized (tabs) {
                tabs.addTab(title, icon, tabPanel, tooltip);
                tabPanels.put(key, tabPanel);
              }
            }
  
            public void removeTab(ModuleTabPanel tabPanel) {
              synchronized (tabs) {
                tabs.remove(tabPanel);
                tabPanels.remove(key);
              }
            }
          }, moduleName);
    }
    return moduleTabPanel;
  }

  /**
   * Invoke a Callable on the UI thread, wait for it to finish, and return the
   * result.
   * 
   * @param <T> return type
   * @param callable wrapper of the method to run on the UI thread
   * @return the return value of callable.call()
   * @throws RuntimeException if an error occurs
   */
  private <T> T invokeAndGet(Callable<T> callable) {
    FutureTask<T> task = new FutureTask<T>(callable);
    try {
      EventQueue.invokeAndWait(task);
      return task.get();
    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    } catch (ExecutionException e) {
      throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Invoke a Runnable on the UI thread and wait for it to finish.
   * 
   * @param runnable
   * @throws RuntimeException if an error occurs
   */
  private void invokeAndWait(Runnable runnable) {
    try {
      EventQueue.invokeAndWait(runnable);
    } catch (InterruptedException e) {
      throw new RuntimeException("Error running on Swing UI thread", e);
    } catch (InvocationTargetException e) {
      throw new RuntimeException("Error running on Swing UI thread", e);
    }
  }

  /**
   * This method contains code that will call certain Apple extensions to make
   * the DevMode app integrate into the system UI a bit better. These methods
   * are called reflectively so that we don't have to build gwt-dev against a
   * no-op stub library.
   */
  private void maybeInitializeOsXApplication() {
    Throwable ex;
    try {
      Class<?> applicationClass = Class.forName("com.apple.eawt.Application");

      topLogger.log(TreeLogger.SPAM, "Got Application class, on OS X");

      Object application = applicationClass.getMethod("getApplication").invoke(
          null);
      assert application != null : "application";

      // Remove the about menu entry
      applicationClass.getMethod("removeAboutMenuItem").invoke(application);

      // Remove the preferences menu entry
      applicationClass.getMethod("removePreferencesMenuItem").invoke(
          application);

      // Make the Dock icon pretty
      applicationClass.getMethod("setDockIconImage", Image.class).invoke(
          application, loadImageIcon("icon128.png").getImage());

      return;
    } catch (ClassNotFoundException e) {
      // Nothing to do here, this is expected on non-Apple JVMs.
      return;
    } catch (RuntimeException e) {
      ex = e;
    } catch (IllegalAccessException e) {
      ex = e;
    } catch (InvocationTargetException e) {
      ex = e;
    } catch (NoSuchMethodException e) {
      ex = e;
    }

    topLogger.log(TreeLogger.WARN, "Unable to initialize some OS X UI support",
        ex);
  }

  /**
   * Set the images for the frame.  On JDK 1.5, only the last icon supplied is
   * used for all needs.
   * 
   * @param logger logger to use for warnings
   * @param icons one or more icons 
   */
  private void setIconImages(TreeLogger logger, ImageIcon... icons) {
    if (icons.length == 0) {
      return;
    }
    Exception caught = null;
    try {
      // if this fails, we fall back to the JDK 1.5 method
      Method method = frame.getClass().getMethod("setIconImages", List.class);
      List<Image> imageList = new ArrayList<Image>();
      for (ImageIcon icon : icons) {
        Image image = icon.getImage();
        if (image != null) {
          imageList.add(image);
        }
      }
      method.invoke(frame, imageList);
      return;
    } catch (SecurityException e) {
      caught = e;
    } catch (IllegalArgumentException e) {
      caught = e;
    } catch (NoSuchMethodException e) {
      // ignore, expected on JDK 1.5
    } catch (IllegalAccessException e) {
      caught = e;
    } catch (InvocationTargetException e) {
      caught = e;
    }
    if (caught != null) {
      logger.log(TreeLogger.WARN, "Unexpected exception setting icon images",
          caught);
    }
    frame.setIconImage(icons[icons.length - 1].getImage());
  }
}
