/* Copyright (c) 2010, Carl Burch. License information is located in the
 * com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */

package com.cburch.logisim.gui.start;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Paint;
import java.net.URL;
import java.util.ArrayList;

import javax.swing.JComponent;

class AboutCredits extends JComponent {
	/** Time to spend freezing the credits before after after scrolling */
	private static final int MILLIS_FREEZE = 1000;
	
	/** Speed of how quickly the scrolling occurs */
	private static final int MILLIS_PER_PIXEL = 20;

	/** Path to Hendrix College's logo - if you want your own logo included,
	 * please add it separately rather than replacing this. */
	private static final String HENDRIX_PATH = "resources/logisim/hendrix.png";
	private static final int HENDRIX_WIDTH = 50;

	private static class CreditsLine {
		private int y;
		private int type;
		private String text;
		private Image img;
		private int imgWidth;
		
		public CreditsLine(int type, String text) {
			this(type, text, null, 0);
		}
		
		public CreditsLine(int type, String text, Image img, int imgWidth) {
			this.y = 0;
			this.type = type;
			this.text = text;
			this.img = img;
			this.imgWidth = imgWidth;
		}
	}
	
	private Color[] colorBase;
	private Paint[] paintSteady;
	private Font[] font;
	
	private int scroll;
	private float fadeStop;
	
	private ArrayList<CreditsLine> lines;
	private int initialLines; // number of lines to show in initial freeze
	private int initialHeight; // computed in code based on above
	private int linesHeight; // computed in code based on above
	
	public AboutCredits() {
		scroll = 0;
		setOpaque(false);
		
		int prefWidth = About.IMAGE_WIDTH + 2 * About.IMAGE_BORDER;
		int prefHeight = About.IMAGE_HEIGHT / 2 + About.IMAGE_BORDER;
		setPreferredSize(new Dimension(prefWidth, prefHeight));
	
		fadeStop = (float) (About.IMAGE_HEIGHT / 4.0);

		colorBase = new Color[] {
				new Color(143, 0, 0),
				new Color(48, 0, 96),
				new Color(48, 0, 96),
		};
		font = new Font[] {
				new Font("Sans Serif", Font.ITALIC, 20),
				new Font("Sans Serif", Font.BOLD, 24),
				new Font("Sans Serif", Font.BOLD, 18),
		};
		paintSteady = new Paint[colorBase.length];
		for (int i = 0; i < colorBase.length; i++) {
			Color hue = colorBase[i];
			paintSteady[i] = new GradientPaint(0.0f, 0.0f, derive(hue, 0),
					0.0f, fadeStop, hue);
		}
		
		URL url = AboutCredits.class.getClassLoader().getResource(HENDRIX_PATH);
		Image hendrixLogo = null;
		if (url != null) {
			hendrixLogo = getToolkit().createImage(url);
		}
		
		// Logisim's policy concerning who is given credit:
		// Past contributors are not acknowledged in the About dialog for the current
		// version, but they do appear in the acknowledgements section of the User's
		// Guide. Current contributors appear in both locations.
		
		lines = new ArrayList<CreditsLine>();
		linesHeight = 0; // computed in paintComponent
		lines.add(new CreditsLine(1, "www.cburch.com/logisim/"));
		lines.add(new CreditsLine(0, Strings.get("creditsRoleLead"),
				hendrixLogo, HENDRIX_WIDTH));
		lines.add(new CreditsLine(1, "Carl Burch"));
		lines.add(new CreditsLine(2, "Hendrix College"));
		initialLines = lines.size();
		lines.add(new CreditsLine(0, Strings.get("creditsRoleGerman")));
		lines.add(new CreditsLine(1, "Uwe Zimmerman"));
		lines.add(new CreditsLine(2, "Uppsala universitet"));
		lines.add(new CreditsLine(0, Strings.get("creditsRoleGreek")));
		lines.add(new CreditsLine(1, "Thanos Kakarountas"));
		lines.add(new CreditsLine(2, "\u03A4.\u0395.\u0399 \u0399\u03BF\u03BD\u03AF\u03C9\u03BD \u039D\u03AE\u03C3\u03C9\u03BD"));
		lines.add(new CreditsLine(0, Strings.get("creditsRolePortuguese")));
		lines.add(new CreditsLine(1, "Theldo Cruz Franqueira"));
		lines.add(new CreditsLine(2, "PUC Minas"));
		lines.add(new CreditsLine(0, Strings.get("creditsRoleRussian")));
		lines.add(new CreditsLine(1, "Ilia Lilov"));
		lines.add(new CreditsLine(2, "\u041C\u043E\u0441\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u0433\u043E\u0441\u0443\u0434\u0430\u0440\u0441\u0442\u0432\u0435\u043D\u043D\u044B\u0439"));
		lines.add(new CreditsLine(2, "\u0443\u043D\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442 \u043F\u0435\u0447\u0430\u0442\u0438"));
		lines.add(new CreditsLine(0, Strings.get("creditsRoleTesting")));
		lines.add(new CreditsLine(1, "Ilia Lilov"));
		lines.add(new CreditsLine(2, "\u041C\u043E\u0441\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u0433\u043E\u0441\u0443\u0434\u0430\u0440\u0441\u0442\u0432\u0435\u043D\u043D\u044B\u0439"));
		lines.add(new CreditsLine(2, "\u0443\u043D\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442 \u043F\u0435\u0447\u0430\u0442\u0438"));
		
		/* If you fork Logisim, feel free to change the above lines, but
		 * please do not change these last four lines! */
		lines.add(new CreditsLine(0, Strings.get("creditsRoleOriginal"),
				hendrixLogo, HENDRIX_WIDTH));
		lines.add(new CreditsLine(1, "Carl Burch"));
		lines.add(new CreditsLine(2, "Hendrix College"));
		lines.add(new CreditsLine(1, "www.cburch.com/logisim/"));
	}
	
	public void setScroll(int value) {
		scroll = value;
		repaint();
	}
	
	private Color derive(Color base, int alpha) {
		return new Color(base.getRed(), base.getGreen(), base.getBlue(), alpha);
	}
	
	@Override
	protected void paintComponent(Graphics g) {
		FontMetrics[] fms = new FontMetrics[font.length];
		for (int i = 0; i < fms.length; i++) {
			fms[i] = g.getFontMetrics(font[i]);
		}
		if (linesHeight == 0) {
			int y = 0;
			int index = -1;
			for (CreditsLine line : lines) {
				index++;
				if (index == initialLines) initialHeight = y;
				if (line.type == 0) y += 10;
				FontMetrics fm = fms[line.type];
				line.y = y + fm.getAscent();
				y += fm.getHeight();
			}
			linesHeight = y;
		}
		
		Paint[] paint = paintSteady;
		int yPos = 0;
		int height = getHeight();
		int initY = Math.min(0, initialHeight - height + About.IMAGE_BORDER);
		int maxY = linesHeight - height - initY;
		int totalMillis = 2 * MILLIS_FREEZE + (linesHeight + height) * MILLIS_PER_PIXEL;
		int offs = scroll % totalMillis;
		if (offs >= 0 && offs < MILLIS_FREEZE) {
			// frozen before starting the credits scroll
			int a = 255 * (MILLIS_FREEZE - offs) / MILLIS_FREEZE;
			if (a > 245) {
				paint = null;
			} else if (a < 15) {
				paint = paintSteady;
			} else {
				paint = new Paint[colorBase.length];
				for (int i = 0; i < paint.length; i++) {
					Color hue = colorBase[i];
					paint[i] = new GradientPaint(0.0f, 0.0f, derive(hue, a),
						0.0f, fadeStop, hue);
				}
			}
			yPos = initY;
		} else if (offs < MILLIS_FREEZE + maxY * MILLIS_PER_PIXEL) {
			// scrolling through credits
			yPos = initY + (offs - MILLIS_FREEZE) / MILLIS_PER_PIXEL;
		} else if (offs < 2 * MILLIS_FREEZE + maxY * MILLIS_PER_PIXEL) {
			// freezing at bottom of scroll
			yPos = initY + maxY;
		} else if (offs < 2 * MILLIS_FREEZE + (linesHeight - initY) * MILLIS_PER_PIXEL) {
			// scrolling bottom off screen
			yPos = initY + (offs - 2 * MILLIS_FREEZE) / MILLIS_PER_PIXEL;
		} else {
			// scrolling next credits onto screen
			int millis = offs - 2 * MILLIS_FREEZE - (linesHeight - initY) * MILLIS_PER_PIXEL;
			paint = null;
			yPos = -height + millis / MILLIS_PER_PIXEL;
		}
		
		int width = getWidth();
		int centerX = width / 2; 
		maxY = getHeight();
		for (CreditsLine line : lines) {
			int y = line.y - yPos;
			if (y < -100 || y > maxY + 50) continue;
			
			int type = line.type;
			if (paint == null) {
				g.setColor(colorBase[type]);
			} else {
				((Graphics2D) g).setPaint(paint[type]);
			}
			g.setFont(font[type]);
			int textWidth = fms[type].stringWidth(line.text);
			g.drawString(line.text, centerX - textWidth / 2, line.y - yPos);
			
			Image img = line.img;
			if (img != null) {
				int x = width - line.imgWidth - About.IMAGE_BORDER;
				int top = y - fms[type].getAscent();
				g.drawImage(img, x, top, this);
			}
		}
	}
}