/*
 * 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 java.util.HashMap;
import java.util.Map;

/**
 * Class used in the module drop-down box so that we can have a unique
 * object in the dropdown.  It is important that identity is maintained, such
 * that if sessionKey, modulePanel, and moduleDisplayName are the same the
 * same SessionModule instance is returned so == means the same as equals.
 */
final class SessionModule {

  /**
   * Used to cache instances so we always return the same SessionModule
   * instance for the same key values.
   */
  private static final Map<SessionModule, SessionModule> instanceCache
      = new HashMap<SessionModule, SessionModule>();

  /**
   * Return a SessionModule instance for a given sessionKey, modulePanel, and
   * moduleDisplayName, re-using an existing instance if it exists.
   *
   * @param sessionKey
   * @param modulePanel
   * @param moduleDisplayName
   * @return unique SessionModule instance matching sessionKey and
   *     moduleDisplayName
   */
  public static SessionModule create(String sessionKey,
      Disconnectable modulePanel, String moduleDisplayName) {
    SessionModule sessionModule = new SessionModule(sessionKey, modulePanel,
        moduleDisplayName);
    if (instanceCache.containsKey(sessionModule)) {
      return instanceCache.get(sessionModule);
    }
    instanceCache.put(sessionModule, sessionModule);
    return sessionModule;
  }

  // @NotNull
  private final Disconnectable modulePanel;

  // @NotNull
  private final String moduleDisplayName;

  // @NotNull
  private final String sessionKey;

  private SessionModule(String sessionKey, Disconnectable modulePanel,
      String moduleDisplayName) {
    if (sessionKey == null) {
      throw new IllegalArgumentException("sessionKey cannot be null");
    }
    if (modulePanel == null) {
      throw new IllegalArgumentException("modulePanel cannot be null");
    }
    if (moduleDisplayName == null) {
      throw new IllegalArgumentException("moduleDisplayName cannot be null");
    }
    this.sessionKey = sessionKey;
    this.modulePanel = modulePanel;
    this.moduleDisplayName = moduleDisplayName;
  }

  // Even though we guarantee identity, we still need equals implemented
  // so we can do so.
  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null || getClass() != obj.getClass()) {
      return false;
    }
    SessionModule other = (SessionModule) obj;
    return sessionKey.equals(other.sessionKey)
        && modulePanel.equals(other.modulePanel)
        && moduleDisplayName.equals(other.moduleDisplayName);
  }

  public String getModuleDisplayName() {
    return moduleDisplayName;
  }

  public Disconnectable getModulePanel() {
    return modulePanel;
  }

  /**
   * @return a unique key representing the session and the module name
   *     within that session.
   */
  public String getStringKey() {
    return sessionKey + moduleDisplayName;
  }

  @Override
  public int hashCode() {
    return sessionKey.hashCode() + 31 * moduleDisplayName.hashCode();
  }

  /**
   * @return a string suitable for human display only, which consists of the
   * module's short name, possibly including a disambiguator for multiple
   * instances of the module name within the same session.
   */
  @Override
  public String toString() {
    return moduleDisplayName;
  }
}