/**
 * 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.Type;
import com.google.gwt.dev.OophmHostedModeBase.TabPanelCollection;
import com.google.gwt.dev.util.BrowserInfo;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.plaf.basic.BasicComboBoxRenderer;

/**
 * A panel which contains all modules in one browser tab.
 */
public class ModuleTabPanel extends JPanel {

  /**
   * A session has a unique session key within a module tab panel, and is
   * identified to the user by the timestamp it was first seen.
   * 
   * <p>Within a session, there will be one or more modules, each with their
   * own ModulePanel.
   */
  public class Session {
    
    private final long createTimestamp;
    
    /**
     * Map from display names in the dropdown box to module panels.
     */
    private final Map<String, ModulePanel> displayNameToModule;
       
    private final IdentityHashMap<ModulePanel, SessionModule> moduleSessionMap;

    private SessionModule lastSelectedModule;
    
    /**
     * Map of module names to the number of times that module has been seen.
     */
    private final Map<String, Integer> moduleCounts;
    
    /**
     * List, in display order, of entries in the module dropdown box.
     */
    private final List<SessionModule> modules;
    
    private final String sessionKey;
    
    public Session(String sessionKey) {
      this.sessionKey = sessionKey;
      createTimestamp = System.currentTimeMillis();
      displayNameToModule = new HashMap<String, ModulePanel>();
      moduleSessionMap = new IdentityHashMap<ModulePanel, SessionModule>();
      modules = new ArrayList<SessionModule>();
      moduleCounts = new HashMap<String, Integer>();
    }

    public synchronized void addModule(String moduleName,
        ModulePanel panel) {
      Integer moduleCount = moduleCounts.get(moduleName);
      if (moduleCount == null) {
        moduleCount = 0;
      }
      moduleCounts.put(moduleName, moduleCount + 1);
      String shortModuleName = getShortModuleName(moduleName);
      if (moduleCount > 0) {
        shortModuleName += " (" + moduleCount + ")";
      }
      SessionModule sessionModule = SessionModule.create(sessionKey,
          panel, shortModuleName);
      modules.add(sessionModule);
      displayNameToModule.put(shortModuleName, panel);
      moduleSessionMap.put(panel, sessionModule);
      // add this item with the key we will use with cardLayout later
      deckPanel.add(panel, sessionModule.getStringKey());
      if (this == currentSession) {
        moduleDropdown.addItem(sessionModule);
        if (moduleDropdown.getItemCount() > 1) {
          moduleDropdownPanel.setEnabled(true);
          moduleDropdownPanel.setVisible(true);
        }
        selectModule(sessionModule);
      }
    }

    public void buildModuleDropdownContents() {
      if (this == currentSession) {
        moduleDropdown.removeAllItems();
        SessionModule firstModule = null;
        for (SessionModule sessionModule : modules) {
         moduleDropdown.addItem(sessionModule);
          if (firstModule == null) {
            firstModule = sessionModule;
          }
        }
        if (moduleDropdown.getItemCount() > 1) {
          moduleDropdownPanel.setEnabled(true);
          moduleDropdownPanel.setVisible(true);
        } else {
          moduleDropdownPanel.setEnabled(false);
          moduleDropdownPanel.setVisible(false);
        }
        if (lastSelectedModule != null) {
          selectModule(lastSelectedModule);
        } else if (firstModule != null) {
          selectModule(firstModule);
        }
      }
    }

    public void disconnectModule(ModulePanel modulePanel) {
      /*
       * TODO(jat): for now, only disconnected modules can be closed.  When
       *     SWT is ripped out and we can pass OOPHM-specific classes through
       *     BrowseWidgetHost.createModuleSpaceHost, we will need to be able
       *     to shutdown the connection from here if it is not already
       *     disconnected.
       */
      SessionModule sessionModule = moduleSessionMap.get(modulePanel);
      moduleSessionMap.remove(modulePanel);
      deckPanel.remove(modulePanel);
      modules.remove(sessionModule);
      switch (modules.size()) {
        case 0: // we just closed the last module in this session
          closeSession(this);
          break;
        case 1: // only one module left, hide dropdown
          moduleDropdownPanel.setEnabled(false);
          moduleDropdownPanel.setVisible(false);
          break;
        default:
          if (lastSelectedModule == sessionModule) {
            // if we closed the active module, switch to the most recent remaining
            lastSelectedModule = modules.get(modules.size() - 1);
          }
          buildModuleDropdownContents();
          break;
      }
    }
    
    public Collection<String> getActiveModules() {
      ArrayList<String> activeModules = new ArrayList<String>();
      for (SessionModule sessionModule : modules) {
        String displayName = sessionModule.toString();
        Disconnectable module = sessionModule.getModulePanel();
        if (!module.isDisconnected()) {
          activeModules.add(displayName);
        }
      }
      return Collections.unmodifiableList(activeModules);
    }

    public String getDisplayName() {
      return DateFormat.getDateTimeInstance().format(new Date(createTimestamp));
    }

    public String getSessionKey() {
      return sessionKey;
    }

    public boolean hasActiveModules() {
      for (SessionModule sessionModule : modules) {
        Disconnectable module = sessionModule.getModulePanel();
        if (!module.isDisconnected()) {
          return true;
        }
      }
      return false;
    }

    @Override
    public String toString() {
      return getDisplayName();
    }

    private String getShortModuleName(String moduleName) {
      int idx = moduleName.lastIndexOf('.');
      if (idx < 0) {
        return moduleName;
      } else {
        return moduleName.substring(idx + 1);
      }
    }

    private void selectModule(SessionModule sessionModule) {
      cardLayout.show(deckPanel, sessionModule.getStringKey());
      lastSelectedModule = sessionModule;
      moduleDropdown.setSelectedItem(sessionModule);
    }
  }

  /**
   * Renderer used to show entries in the module dropdown box.
   */
  private static class SessionModuleRenderer extends BasicComboBoxRenderer {

    @Override
    public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus) {
      // the superclass just returns this, so we don't save the result and
      // cast it back to a label
      super.getListCellRendererComponent(list, value, index,
          isSelected, cellHasFocus);
      if (value instanceof SessionModule) {
        SessionModule sessionModule = (SessionModule) value;
        if (sessionModule.getModulePanel().isDisconnected()) {
          setForeground(DISCONNECTED_DROPDOWN_COLOR);
          setFont(getFont().deriveFont(Font.ITALIC));
        }
        // TODO(jat): set font to bold/etc if the window has new messages
      }
      return this;
    }
  }

  /**
   * Renderer used to show entries in the session dropdown box.
   */
  private static class SessionRenderer extends BasicComboBoxRenderer {
  
    @Override
    public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus) {
      // the superclass just returns this, so we don't save the result and
      // cast it back to a label
      super.getListCellRendererComponent(list, value, index,
          isSelected, cellHasFocus);
      if (value instanceof Session) {
        Session session = (Session) value;
        if (!session.hasActiveModules()) {
          setForeground(DISCONNECTED_DROPDOWN_COLOR);
          setFont(getFont().deriveFont(Font.ITALIC));
        }
        // TODO(jat): set font to bold/etc if new modules were added
      }
      return this;
    }
  }

  public static final Color DISCONNECTED_DROPDOWN_COLOR = Color.decode("0x808080");

  private CardLayout cardLayout;

  private Session currentSession;

  private JPanel deckPanel;

  private JComboBox moduleDropdown;

  private JComboBox sessionDropdown;

  private final Map<String, Session> sessions = new HashMap<String, Session>();

  private final TabPanelCollection tabPanelCollection;

  private JPanel topPanel;

  private JPanel sessionDropdownPanel;

  private JPanel moduleDropdownPanel;

  /**
   * Create a panel which will be a top-level tab in the OOPHM UI.  Each of
   * these tabs will contain one or more sessions, and within that one or
   * more module instances. 
   * 
   * @param userAgent
   * @param remoteSocket
   * @param url
   * @param tabPanelCollection
   * @param moduleName used just for the tab name in the event that the plugin
   *     is an older version that doesn't supply the url
   */
  public ModuleTabPanel(String userAgent, String remoteSocket, String url,
      TabPanelCollection tabPanelCollection, String moduleName) {
    super(new BorderLayout());
    this.tabPanelCollection = tabPanelCollection;
    topPanel = new JPanel();
    sessionDropdownPanel = new JPanel();
    sessionDropdownPanel.add(new JLabel("Session: "));
    sessionDropdown = new JComboBox();
    sessionDropdown.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        Session session = (Session) sessionDropdown.getSelectedItem();
        selectSession(session);
      }

    });
    sessionDropdown.setRenderer(new SessionRenderer());
    sessionDropdownPanel.add(sessionDropdown);
    sessionDropdownPanel.setEnabled(false);
    sessionDropdownPanel.setVisible(false);
    topPanel.add(sessionDropdownPanel);
    moduleDropdownPanel = new JPanel();
    moduleDropdownPanel.add(new JLabel("Module: "));
    moduleDropdown = new JComboBox();
    moduleDropdown.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        SessionModule sessionModule = (SessionModule)
            moduleDropdown.getSelectedItem();
        if (sessionModule != null) {
          // may be null when removeAllItems is called
          currentSession.selectModule(sessionModule);
        }
      }
    });
    moduleDropdown.setRenderer(new SessionModuleRenderer());
    moduleDropdownPanel.add(moduleDropdown);
    moduleDropdownPanel.setEnabled(false);
    moduleDropdownPanel.setVisible(false);
    topPanel.add(moduleDropdownPanel);
    add(topPanel, BorderLayout.NORTH);
    deckPanel = new JPanel();
    cardLayout = new CardLayout();
    deckPanel.setLayout(cardLayout);
    add(deckPanel);
    BrowserInfo browserInfo = BrowserInfo.getBrowserInfo(userAgent);
    
    // Construct the tab title and tooltip
    String tabTitle = url;
    if (tabTitle == null) {
      int idx = moduleName.lastIndexOf('.');
      tabTitle = moduleName.substring(idx + 1);
      url = "";
    } else {
      try {
        URL parsedUrl = new URL(url);
        tabTitle = getTabTitle(parsedUrl);
        // rebuild the URL omitting query params and the hash
        StringBuilder buf = new StringBuilder();
        buf.append(parsedUrl.getProtocol()).append(':');
        if (parsedUrl.getAuthority() != null
            && parsedUrl.getAuthority().length() > 0) {
          buf.append("//").append(parsedUrl.getAuthority());
        }
        if (parsedUrl.getPath() != null) {
          buf.append(parsedUrl.getPath());
        }
        buf.append(' '); // space for tooltip below
        url = buf.toString(); 
      } catch (MalformedURLException e1) {
        // Ignore and just use the full URL
      }
    }

    ImageIcon browserIcon = browserInfo.getIcon();
    String shortName = browserInfo.getShortName();
    if (browserIcon == null) {
      if (shortName != null) {
        tabTitle += " (" + shortName + ")";
      }
    }
    tabPanelCollection.addTab(this, browserIcon, tabTitle, url + "from "
        + remoteSocket + " on " + userAgent);
  }

  public synchronized ModulePanel addModuleSession(Type maxLevel,
      String moduleName,
      String sessionKey,
      File logFile) {
    Session session = findOrCreateSession(sessionKey);
    
    ModulePanel panel = new ModulePanel(maxLevel, moduleName, session, logFile);
    return panel;
  }

  private synchronized void addSession(Session session) {
    sessionDropdown.addItem(session);
    sessionDropdown.setSelectedItem(session);
    if (sessionDropdown.getItemCount() > 1) {
      sessionDropdownPanel.setEnabled(true);
      sessionDropdownPanel.setVisible(true);
    }
    selectSession(session);
  }

  private synchronized void closeSession(Session session) {
    sessionDropdown.removeItem(session);
    sessions.remove(session.getSessionKey());
    switch (sessionDropdown.getItemCount()) {
      case 0: // last session closed, close tab
        tabPanelCollection.removeTab(this);
        return;
      case 1: // one session left, remove dropdown
        sessionDropdownPanel.setEnabled(false);
        sessionDropdownPanel.setVisible(false);
        break;
      default: // more than 1 left, do nothing
        break;
    }
    if (session == currentSession) {
      selectSession((Session) sessionDropdown.getItemAt(
          sessionDropdown.getItemCount() - 1));
    }
  }
  
  /**
   * Return the proper Session object for this session, creating it if needed.
   * 
   * @param sessionKey unique key for this session
   * @return Session instance
   */
  private synchronized Session findOrCreateSession(String sessionKey) {
    Session session = sessions.get(sessionKey);
    if (session == null) {
      session = new Session(sessionKey);
      sessions.put(sessionKey, session);
      addSession(session);
    }
    return session;
  }

  private String getTabTitle(URL parsedUrl) {
    String tabTitle = parsedUrl.getPath();
    if (tabTitle.length() > 0) {
      int startIdx = tabTitle.lastIndexOf('/');
      int lastIdx = tabTitle.length();
      if (tabTitle.endsWith(".html")) {
        lastIdx -= 5;
      } else if (tabTitle.endsWith(".htm")) {
        lastIdx -= 4;
      }
      tabTitle = tabTitle.substring(startIdx + 1, lastIdx);
    } else {
      tabTitle = "/";
    }
    return tabTitle;
  }

  private void selectSession(Session session) {
    currentSession = session;
    if (session != null) {
      // can be null when last session removed
      session.buildModuleDropdownContents();
    }
  }
}
