package de.emvau.mvstandardgui;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;

import com.ulcjava.base.application.IRendererComponent;
import com.ulcjava.base.application.ULCLabel;
import com.ulcjava.base.application.ULCTree;
import com.ulcjava.base.application.event.ActionEvent;
import com.ulcjava.base.application.event.IActionListener;
import com.ulcjava.base.application.tree.DefaultTreeCellRenderer;
import com.ulcjava.base.application.tree.ITreeCellRenderer;
import com.ulcjava.base.application.util.Color;
import com.ulcjava.base.application.util.ULCIcon;
import com.ulcjava.base.client.UILabel;
import com.ulcjava.base.shared.IUlcEventConstants;
import com.ulcjava.base.shared.internal.Anything;

import de.emvau.application.tree.GeVoSelectionNode;
import de.emvau.mvkerngui.IMVTreeView;
import de.emvau.mvkerngui.ViewNodeDescription;

public abstract class TestTreeViewRenderer extends DefaultTreeCellRenderer implements ITreeCellRenderer
{
  protected IMVTreeView treeView = null;
  private Map loadedIcons = new HashMap();

  public TestTreeViewRenderer(IMVTreeView treeView)
  {
    this.treeView = treeView;
  }

  public TestTreeViewRenderer()
  {
  }

  /**
   * Setzen aller Propertys zu der TreeNode-Anzeige
   * 
   * @param tree MVTreeView
   * @param value aktuell zu zeichnendes MVTreeNode
   * @param selected true wenn die TreeNode selektiert ist
   * @param expanded true wenn die TreeNode expanded ist
   * @param leaf true wenn die TreeNode keine Kinderknoten hat
   * @param hasFocus true wenn die TreeNode fokusiert ist
   * 
   * @return IRendererComponent Renderer-Object
   */
  public IRendererComponent getTreeCellRendererComponent(ULCTree tree, Object value, boolean selected, boolean expanded, boolean leaf, boolean hasFocus)
  {
    ULCLabel label = this.init(value);

    label.setIcon(createIcon(value, expanded, leaf));
    label.setBackground(getBackgroundFor(value, selected, hasFocus));
    label.setForeground(getForegroundFor(selected));

    return label;
  }

  /**
   * Erzeugt entsprechendes Icon fur die Anzeige des TreeNodes
   */
  protected ULCIcon createIcon(Object value, boolean expanded, boolean leaf)
  {
    ViewNodeDescription viewNode = null;
    Object userObject = ((MVTreeNode) value).getUserObject();

    if (userObject instanceof ViewNodeDescription)
      viewNode = (ViewNodeDescription) userObject;
    else if (userObject instanceof ViewNodeFormComponent)
      viewNode = ((ViewNodeFormComponent) userObject).getViewNodeDescription();
    else if (userObject instanceof GeVoSelectionNode)
    {

    }
    boolean valid = true;

    if (value instanceof MVTreeNode)
      valid = ((MVTreeNode) value).isValid();

    return this.getIconFor(viewNode, expanded, leaf, valid);
  }

  /**
   * Liefert anhand des Iconnamens das bereits gelesene und gecachte Icon zurueck.
   * 
   * @param String iconName Icon-Name mit Extension
   * @return MVIcon Instanz des Icons
   */
  public final MVIcon get(String iconName)
  {
    MVIcon icon = null;

    if ((iconName != null) && !iconName.equals(""))
    {
      if (!this.loadedIcons.containsKey(iconName))
      {
        icon = MVIcon.create(iconName, this.treeView.getKonfigManager());
        if (icon != null)
          this.loadedIcons.put(iconName, icon);
      }
      else
        icon = (MVIcon) this.loadedIcons.get(iconName);
    }
    return icon;
  }

  /**
   * Setzen der Hintergrundfarbe des TreeNodes
   */
  public abstract Color getBackgroundFor(Object value, boolean selected, boolean hasFocus);

  /**
   * Setzen der Vordergrundfarbe des TreeNodes
   */
  public abstract Color getForegroundFor(boolean selected);

  /**
   * Hilfsmethode zur Erzeugung des TreeNode-Icons
   */
  public abstract ULCIcon getIconFor(ViewNodeDescription viewNode, boolean expanded, boolean leaf, boolean valid);

  private ULCLabel init(Object value)
  {
    ViewNodeDescription viewNode = null;
    Object userObject = ((MVTreeNode) value).getUserObject();

    if (userObject instanceof ViewNodeDescription)
      viewNode = (ViewNodeDescription) userObject;
    else if (userObject instanceof ViewNodeFormComponent)
      viewNode = ((ViewNodeFormComponent) userObject).getViewNodeDescription();

    if (viewNode != null && viewNode.isActivateNode())
    {
      addActionListener(new ActionLabelListener((MVTreeNode) value, viewNode));
    }
    return this;
  }

  public void addActionListener(IActionListener listener)
  {
    super.internalAddListener(IUlcEventConstants.ACTION_EVENT, listener);
  }

  public void removeActionListener(IActionListener listener)
  {
    internalRemoveListener(IUlcEventConstants.ACTION_EVENT, listener);
  }

  protected void handleEvent(int listenerType, int eventId, Anything args)
  {
    if (listenerType == IUlcEventConstants.ACTION_EVENT)
    {
      distributeToListeners(new ActionEvent(this, null));
    }
    else
    {
      super.handleEvent(listenerType, eventId, args);
    }
  }

  protected String typeString()
  {
    return UIActionLabel.class.getName();
  }

  public class UIActionLabel extends UILabel
  {
    public void restoreState(Anything args)
    {
      super.restoreState(args);

      getBasicComponent().addMouseListener(new ActionHandler());
    }

    private class ActionHandler extends MouseAdapter
    {

      public void mouseClicked(MouseEvent event)
      {
        if (isIconFocused(event))
        {
          sendOptionalEventULC(IUlcEventConstants.ACTION_EVENT, IUlcEventConstants.ACTION_PERFORMED);
        }
      }

      private boolean isIconFocused(MouseEvent event)
      {
        Object source = event.getSource();
        UiJDnDLabel label = (UiJDnDLabel) event.getSource();
        int horizontalTextPos = label.getHorizontalTextPosition() + 1;
        int x = event.getX() - 1;
        if (x <= horizontalTextPos)
        {
          // System.out.println("Maus-Zeiger: " + x + " Textposition: " + horizontalTextPos);
          return true;
        }
        return false;
      }
    }
  }

  public class ActionLabelListener implements IActionListener
  {
    private ViewNodeDescription viewNode = null;
    private MVTreeNode node = null;

    public ActionLabelListener(MVTreeNode node, ViewNodeDescription viewNode)
    {
      this.viewNode = viewNode;
    }

    public void actionPerformed(ActionEvent event)
    {
      // Programmspezifische Aktion ausfuehren -> aktivieren/deaktivieren der Knoten
      // ....
    }
  }

}
