/*
 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.revplot;

import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevFlag;

/**
 * Basic commit graph renderer for graphical user interfaces.
 * <p>
 * Lanes are drawn as columns left-to-right in the graph, and the commit short
 * message is drawn to the right of the lane lines for this cell. It is assumed
 * that the commits are being drawn as rows of some sort of table.
 * <p>
 * Client applications can subclass this implementation to provide the necessary
 * drawing primitives required to display a commit graph. Most of the graph
 * layout is handled by this class, allowing applications to implement only a
 * handful of primitive stubs.
 * <p>
 * This class is suitable for us within an AWT TableCellRenderer or within a SWT
 * PaintListener registered on a Table instance. It is meant to rubber stamp the
 * graphics necessary for one row of a plotted commit list.
 * <p>
 * Subclasses should call {@link #paintCommit(PlotCommit, int)} after they have
 * otherwise configured their instance to draw one commit into the current
 * location.
 * <p>
 * All drawing methods assume the coordinate space for the current commit's cell
 * starts at (upper left corner is) 0,0. If this is not true (like say in SWT)
 * the implementation must perform the cell offset computations within the
 * various draw methods.
 *
 * @param <TLane>
 *            type of lane being used by the application.
 * @param <TColor>
 *            type of color object used by the graphics library.
 */
public abstract class AbstractPlotRenderer<TLane extends PlotLane, TColor> {
	private static final int LANE_WIDTH = 14;

	private static final int LINE_WIDTH = 2;

	private static final int LEFT_PAD = 2;

	/**
	 * Paint one commit using the underlying graphics library.
	 *
	 * @param commit
	 *            the commit to render in this cell. Must not be null.
	 * @param h
	 *            total height (in pixels) of this cell.
	 */
	protected void paintCommit(final PlotCommit<TLane> commit, final int h) {
		final int dotSize = computeDotSize(h);
		final TLane myLane = commit.getLane();
		final int myLaneX = laneC(myLane);
		final TColor myColor = laneColor(myLane);

		int maxCenter = 0;
		for (final TLane passingLane : (TLane[]) commit.passingLanes) {
			final int cx = laneC(passingLane);
			final TColor c = laneColor(passingLane);
			drawLine(c, cx, 0, cx, h, LINE_WIDTH);
			maxCenter = Math.max(maxCenter, cx);
		}

		final int nParent = commit.getParentCount();
		for (int i = 0; i < nParent; i++) {
			final PlotCommit<TLane> p;
			final TLane pLane;
			final TColor pColor;
			final int cx;

			p = (PlotCommit<TLane>) commit.getParent(i);
			pLane = p.getLane();
			if (pLane == null)
				continue;

			pColor = laneColor(pLane);
			cx = laneC(pLane);

			if (Math.abs(myLaneX - cx) > LANE_WIDTH) {
				if (myLaneX < cx) {
					final int ix = cx - LANE_WIDTH / 2;
					drawLine(pColor, myLaneX, h / 2, ix, h / 2, LINE_WIDTH);
					drawLine(pColor, ix, h / 2, cx, h, LINE_WIDTH);
				} else {
					final int ix = cx + LANE_WIDTH / 2;
					drawLine(pColor, myLaneX, h / 2, ix, h / 2, LINE_WIDTH);
					drawLine(pColor, ix, h / 2, cx, h, LINE_WIDTH);
				}
			} else {
				drawLine(pColor, myLaneX, h / 2, cx, h, LINE_WIDTH);
			}
			maxCenter = Math.max(maxCenter, cx);
		}

		final int dotX = myLaneX - dotSize / 2 - 1;
		final int dotY = (h - dotSize) / 2;

		if (commit.getChildCount() > 0)
			drawLine(myColor, myLaneX, 0, myLaneX, dotY, LINE_WIDTH);

		if (commit.has(RevFlag.UNINTERESTING))
			drawBoundaryDot(dotX, dotY, dotSize, dotSize);
		else
			drawCommitDot(dotX, dotY, dotSize, dotSize);

		int textx = Math.max(maxCenter + LANE_WIDTH / 2, dotX + dotSize) + 8;
		int n = commit.refs.length;
		for (int i = 0; i < n; ++i) {
			textx += drawLabel(textx + dotSize, h/2, commit.refs[i]);
		}

		final String msg = commit.getShortMessage();
		drawText(msg, textx + dotSize + n*2, h / 2);
	}

	/**
	 * Draw a decoration for the Ref ref at x,y
	 *
	 * @param x
	 *            left
	 * @param y
	 *            top
	 * @param ref
	 *            A peeled ref
	 * @return width of label in pixels
	 */
	protected abstract int drawLabel(int x, int y, Ref ref);

	private int computeDotSize(final int h) {
		int d = (int) (Math.min(h, LANE_WIDTH) * 0.50f);
		d += (d & 1);
		return d;
	}

	/**
	 * Obtain the color reference used to paint this lane.
	 * <p>
	 * Colors returned by this method will be passed to the other drawing
	 * primitives, so the color returned should be application specific.
	 * <p>
	 * If a null lane is supplied the return value must still be acceptable to a
	 * drawing method. Usually this means the implementation should return a
	 * default color.
	 *
	 * @param myLane
	 *            the current lane. May be null.
	 * @return graphics specific color reference. Must be a valid color.
	 */
	protected abstract TColor laneColor(TLane myLane);

	/**
	 * Draw a single line within this cell.
	 *
	 * @param color
	 *            the color to use while drawing the line.
	 * @param x1
	 *            starting X coordinate, 0 based.
	 * @param y1
	 *            starting Y coordinate, 0 based.
	 * @param x2
	 *            ending X coordinate, 0 based.
	 * @param y2
	 *            ending Y coordinate, 0 based.
	 * @param width
	 *            number of pixels wide for the line. Always at least 1.
	 */
	protected abstract void drawLine(TColor color, int x1, int y1, int x2,
			int y2, int width);

	/**
	 * Draw a single commit dot.
	 * <p>
	 * Usually the commit dot is a filled oval in blue, then a drawn oval in
	 * black, using the same coordinates for both operations.
	 *
	 * @param x
	 *            upper left of the oval's bounding box.
	 * @param y
	 *            upper left of the oval's bounding box.
	 * @param w
	 *            width of the oval's bounding box.
	 * @param h
	 *            height of the oval's bounding box.
	 */
	protected abstract void drawCommitDot(int x, int y, int w, int h);

	/**
	 * Draw a single boundary commit (aka uninteresting commit) dot.
	 * <p>
	 * Usually a boundary commit dot is a light gray oval with a white center.
	 *
	 * @param x
	 *            upper left of the oval's bounding box.
	 * @param y
	 *            upper left of the oval's bounding box.
	 * @param w
	 *            width of the oval's bounding box.
	 * @param h
	 *            height of the oval's bounding box.
	 */
	protected abstract void drawBoundaryDot(int x, int y, int w, int h);

	/**
	 * Draw a single line of text.
	 * <p>
	 * The font and colors used to render the text are left up to the
	 * implementation.
	 *
	 * @param msg
	 *            the text to draw. Does not contain LFs.
	 * @param x
	 *            first pixel from the left that the text can be drawn at.
	 *            Character data must not appear before this position.
	 * @param y
	 *            pixel coordinate of the centerline of the text.
	 *            Implementations must adjust this coordinate to account for the
	 *            way their implementation handles font rendering.
	 */
	protected abstract void drawText(String msg, int x, int y);

	private int laneX(final PlotLane myLane) {
		final int p = myLane != null ? myLane.getPosition() : 0;
		return LEFT_PAD + LANE_WIDTH * p;
	}

	private int laneC(final PlotLane myLane) {
		return laneX(myLane) + LANE_WIDTH / 2;
	}
}
