/*
 * 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.shell.WrapLayout;
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(new WrapLayout());
    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(new WrapLayout());
    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);
    cardLayout = new CardLayout();
    deckPanel = new JPanel(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();
    }
  }
}
