/**
 * 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: SimpleMember.java,v 1.14 2005/06/15 23:43:02 pietschy Exp $
 */

package org.pietschy.command;

import org.pietschy.command.log.Logger;

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


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

   private Command command;
   private CommandGroup parent;

   protected SimpleMember(CommandGroup parent, Command command)
   {
      log.enter("SimpleMember");
      log.param("parent", String.valueOf(parent));
      log.param("command", String.valueOf(command));

      this.parent = parent;
      this.command = command;

      if (!parent.isAllowableMember(command))
         throw new IllegalArgumentException("Command: " + command +
                                            " is not allowed in group: " + parent);

      log.exit("SimpleMember");
   }

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

      if (factory instanceof MenuFactory)
      {
         JMenuItem menu = findExistingMenu(command, previousButtons);
         if (menu == null)
         {
            menu = command.createMenuItem(((MenuFactory) factory), faceId);
            // configureMenu context with the group that created it.
            RenderContext.get(menu).setGroupContext(parent, buttonIndex);
            // now we render the button again as the original attempt when the button
            // was created didn't have the group information.
            command.configureButtonAppearance(menu);
         }


         container.add(menu);
      }
      else if (factory instanceof ButtonFactory)
      {
         AbstractButton button = findExistingButton(command, previousButtons);
         if (button == null)
         {
            button = command.createButton(((ButtonFactory) factory), faceId);
            // configureMenu context with the group that created it.
            RenderContext.get(button).setGroupContext(parent, buttonIndex);
            // now we render the button again as the original attempt when the button
            // was created didn't have the group information.
            command.configureButtonAppearance(button);
         }

         container.add(button);
      }


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

   protected JMenuItem
   findExistingMenu(Command command, List buttons)
   {
      for (Iterator iter = buttons.iterator(); iter.hasNext();)
      {
         AbstractButton button = (AbstractButton) iter.next();
         if (button instanceof JMenuItem && command.isAttachedTo(button))
         {
            iter.remove();
            return (JMenuItem) button;
         }
      }

      return null;
   }

   protected AbstractButton
   findExistingButton(Command command, List buttons)
   {
      for (Iterator iter = buttons.iterator(); iter.hasNext();)
      {
         AbstractButton button = (AbstractButton) iter.next();
         if (!(button instanceof JMenuItem) && command.isAttachedTo(button))
         {
            iter.remove();
            return button;
         }
      }

      return null;
   }

   public void
   addNotify()
   {
      log.enter("addNotify");
      command.addNotify(parent);
      log.exit("addNotify()");
   }

   public void
   removeNotify()
   {
      log.enter("removeNotify");
      command.removeNotify(parent);
      log.exit("removeNotify()");
   }

   public boolean
   isMemberFor(Command command)
   {
      log.enter("isMemberFor");
      log.param("command", command);
      boolean result = this.command.equals(command);
      log.returned(result ? Boolean.TRUE : Boolean.FALSE);
      log.exit("isMemberFor");
      return result;
   }

   /**
    * 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)
   {
      return command.getId().equals(c.getId());
   }

   public void
   acceptVisitor(GroupVisitor visitor)
   {
      if (command instanceof ActionCommand)
         visitor.visit((ActionCommand) command);
      else
         visitor.visit((CommandGroup) command);

   }

   /**
    * 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() + "[" + command.getId() + "]";
   }


}
