/**
 * 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.SwingUI.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 agentIconBytes 
   * @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,
      byte[] agentIconBytes, 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);
    
    // 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 = null;
    if (agentIconBytes != null) {
      browserIcon = new ImageIcon(agentIconBytes);
    }
    String shortName = BrowserInfo.getShortName(userAgent);
    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();
    }
  }
}
