/*
 * 03/21/2010
 *
 * Copyright (C) 2010 Robert Futrell
 * robert_futrell at users.sourceforge.net
 * http://fifesoft.com/rsyntaxtextarea
 *
 * This library is distributed under a modified BSD license.  See the included
 * RSTALanguageSupport.License.txt file for details.
 */
package org.fife.rsta.ac.java;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.Map;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JList;

import org.fife.ui.autocomplete.Completion;
import org.fife.ui.autocomplete.CompletionCellRenderer;
import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities;


/**
 * Cell renderer for Java auto-completion.  This renderer attempts to be
 * fast due to the possibility of many (100+) auto-completions dynamically
 * generated for large Java classes.  Using Swing's HTML support is simply
 * too slow (see {@link CompletionCellRenderer}).<p>
 *
 * The color scheme for this renderer mimics that found in Eclipse.
 *
 * @author Robert Futrell
 * @version 1.0
 */
public class JavaCellRenderer extends DefaultListCellRenderer {

	private JList list;
	private boolean selected;
	private boolean evenRow;
	private JavaSourceCompletion jsc;

	/**
	 * The alternating background color, or <code>null</code> for none.
	 */
	private static Color altBG;

	/**
	 * This is used instead of jsc for "incomplete" stuff, like classes,
	 * interfaces, etc. read from jars (don't yet read the class in, for
	 * example).
	 */
	private Completion nonJavaCompletion;

	/**
	 * Whether to not display extra info (type, etc.)in completion text, just
	 * the completion's name.  The default is <code>false</code>.
	 */
	private boolean simpleText;


	/**
	 * Returns the background color to use on alternating lines.
	 *
	 * @return The alternate background color.  If this is <code>null</code>,
	 *         alternating colors are not used.
	 * @see #setAlternateBackground(Color)
	 */
	public static Color getAlternateBackground() {
		return altBG;
	}


	/**
	 * Returns the renderer.
	 *
	 * @param list The list of choices being rendered.
	 * @param value The {@link Completion} being rendered.
	 * @param index The index into <code>list</code> being rendered.
	 * @param selected Whether the item is selected.
	 * @param hasFocus Whether the item has focus.
	 */
	public Component getListCellRendererComponent(JList list, Object value,
						int index, boolean selected, boolean hasFocus) {

		super.getListCellRendererComponent(list, value, index, selected, hasFocus);

		setText("Foobar"); // Just something to give it proper height
		this.list = list;
		this.selected = selected;

		if (value instanceof JavaSourceCompletion) {
			jsc = (JavaSourceCompletion)value;
			nonJavaCompletion = null;
			setIcon(jsc.getIcon());
		}
		else {
			jsc = null;
			nonJavaCompletion = (Completion)value;
			setIcon(nonJavaCompletion.getIcon());
		}

		evenRow = (index&1) == 0;
		if (altBG!=null && evenRow && !selected) {
			setBackground(altBG);
		}

		return this;

	}


	protected void paintComponent(Graphics g) {

		// Set up rendering hints to look as close to native as possible
		Graphics2D g2d = (Graphics2D)g;
		Object old = null;

		// First, try to use the rendering hint set that is "native".
		Map hints = RSyntaxUtilities.getDesktopAntiAliasHints();
		if (hints!=null) {
			old = g2d.getRenderingHints();
			g2d.addRenderingHints(hints);
		}
		// If a "native" set isn't found, just turn on standard text AA.
		else {
			old = g2d.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING);
			g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
								RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		}

//		if (jsc!=null) {
//			setText(null); // Stop "Foobar" from being painted
//		}

		// We never paint "selection" around the icon, to imitate Eclipse
		final int iconW = 18;
		int h = getHeight();
		if (!selected) {
			g.setColor(getBackground());
			g.fillRect(0,0, getWidth(),h);
		}
		else {
			g.setColor(altBG!=null && evenRow ? altBG : list.getBackground());
			g.fillRect(0,0, iconW,h);
			g.setColor(getBackground()); // Selection color
			g.fillRect(iconW, 0, getWidth()-iconW, h);
		}
		if (getIcon()!=null) {
			int y = (h - getIcon().getIconHeight())/2;
			getIcon().paintIcon(this, g, 0, y);
		}

		int x = getX() + iconW + 2;
		g.setColor(selected ? list.getSelectionForeground() :
								list.getForeground());
		if (jsc!=null && !simpleText) {
			jsc.rendererText(g, x, g.getFontMetrics().getHeight(), selected);
		}
		else {
			Completion c = jsc!=null ? jsc : nonJavaCompletion;
			if (c!=null) {
				g.drawString(c.toString(), x, g.getFontMetrics().getHeight());
			}
		}

		// Restore rendering hints appropriately.
		if (hints!=null) {
			g2d.addRenderingHints((Map)old);
		}
		else {
			g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, old);
		}

	}


	/**
	 * Sets the background color to use on alternating lines.
	 *
	 * @param altBG The new alternate background color.  If this is
	 *        <code>null</code>, alternating lines will not use different
	 *        background colors.
	 * @see #getAlternateBackground()
	 */
	public static void setAlternateBackground(Color altBG) {
		JavaCellRenderer.altBG = altBG;
	}


	/**
	 * Sets whether to display "simple" text about the completion - just the
	 * name, no type information, etc.  The default value is <code>false</code>.
	 *
	 * @param simple Whether to display "simple" text about the completion.
	 */
	public void setSimpleText(boolean simple) {
		simpleText = simple;
	}


}