/**
 * GUI Commands
 * Copyright 2004 Andrew Pietsch
 *
 * 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.
 *
 * $Id: LazyMember.java,v 1.12 2006/02/26 00:59:06 pietschy Exp $
 */

package org.pietschy.command;

import org.pietschy.command.log.Logger;

import javax.swing.*;
import java.util.List;


class
LazyMember
extends AbstractGroupMember
{
   private static final Logger log = CommandManager.getLogger(LazyMember.class);

   private CommandGroup parent;
   private GroupMember delegate;
   private String commandId;
   private boolean inlineGroup;
   private boolean addedWhileLazy = false;


   protected LazyMember(CommandGroup parent, String commandId)
   {
      this(parent, commandId, false);
   }

   protected LazyMember(CommandGroup parent, String commandId, boolean inlineGroup)
   {
      if (parent == null)
         throw new NullPointerException("parent is null");

      this.parent = parent;
      this.commandId = commandId;
      this.inlineGroup = inlineGroup;
   }



   public void
   addComponentTo(JComponent container, Object factory, String faceId, List previousButtons, int buttonIndex)
   {
      log.enter("addTo");
      log.param("container", String.valueOf(container.getClass()));

      if (prepared())
         delegate.addComponentTo(container, factory, faceId, previousButtons, buttonIndex);

      log.exit("addTo()");
   }

   /**
    * Attempts to retreive the command that this member represents.  If the command
    * isn't in this groups {@link CommandManager} then this method will return null.
    *
    * @return the {@link Command} this member respresents, or null if it isn't available.
    */
   protected boolean
   prepared()
   {

      if (delegate != null)
         return true;

      CommandManager commandManager = parent.getCommandManager();

      if (commandManager.isGroup(commandId))
      {
         CommandGroup group = commandManager.getGroup(commandId);
         if (group != null)
         {
            if (inlineGroup)
               delegate = parent.getMemberFactory().createInlineMember(parent, group);
            else
               delegate = parent.getMemberFactory().createSimpleMember(parent, group);
         }
      }
      else
      {
         Command command = commandManager.getCommand(commandId);

         if (command != null)
         {
            if (inlineGroup)
               log.warn("Group member '" + commandId + "' specified as inline but isn't a group.  Inline request ignored");

            delegate = parent.getMemberFactory().createSimpleMember(parent, command);
         }
      }

      if (delegate != null && addedWhileLazy)
         delegate.addNotify();

      return delegate != null;
   }

   public boolean
   isMemberFor(Command c)
   {
      return commandId.equals(c.getId());
   }

   /**
    * Checks if this group is dependant on the specified command.
    *
    * @param c the Command in question.
    * @return <tt>true</tt> if this member
    */
   public boolean
   isDependantOn(Command c)
   {
      if (prepared())
         return delegate.isDependantOn(c);

      return commandId.equals(c.getId());
   }


   public void
   acceptVisitor(GroupVisitor visitor)
   {
      if (prepared())
         delegate.acceptVisitor(visitor);
   }

   public void
   addNotify()
   {
      if (prepared())
         delegate.addNotify();
      else
         addedWhileLazy = true;
   }

   public void
   removeNotify()
   {
      if (prepared())
         delegate.removeNotify();
      else
         addedWhileLazy = false;
   }

   /**
    * Returns a string representation of the object. In general, the
    * <code>toString</code> method returns a string that
    * "textually represents" this object. The result should
    * be a concise but informative representation that is easy for a
    * person to read.
    * It is recommended that all subclasses override this method.
    * <p/>
    * The <code>toString</code> method for class <code>Object</code>
    * returns a string consisting of the name of the class of which the
    * object is an instance, the at-sign character `<code>@</code>', and
    * the unsigned hexadecimal representation of the hash code of the
    * object. In other words, this method returns a string equal to the
    * value of:
    * <blockquote>
    * <pre>
    * getClass().getName() + '@' + Integer.toHexString(hashCode())
    * </pre></blockquote>
    *
    * @return a string representation of the object.
    */
   public String toString()
   {
      return getClass().getName() + "[" + commandId + "]";
   }


}
