/*******************************************************************************
 * Copyright (c) 2011 LWJGL Project and others
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html, and under the terms of the 
 * BSD license, see http://lwjgl.org/license.php for details.
 *
 * Contributors:
 *     Kristian Duske - FPS Status Line Item
 *******************************************************************************/

package org.lwjgl.info;

import java.util.logging.Logger;

import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.action.StatusLineLayoutData;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;

/**
 * Displays FPS information in the Eclipse status bar.
 * 
 * @author Kristian Duske
 * @version $Revision$
 * @since 22.05.2008
 * @see $HeadURL$
 */
public class FpsStatusLineItem extends ContributionItem {

	private static final int CHAR_WIDTH = 8;

	private static final int INDENT = 3;

	@SuppressWarnings("unused")
	private static final Logger log = Logger.getLogger(FpsStatusLineItem.class
			.getName());

	private static final int NUM_FRAMES = 500;

	private static final long TIMEOUT = 300;

	private int m_fixedHeight = -1;

	private int m_fixedWidth = -1;

	private long[] m_frames = new long[NUM_FRAMES];

	private int m_index = 0;

	private int m_count = -1;

	private double avg;

	private long m_lastFrame = -1;

	private CLabel m_label;

	/**
	 * 
	 */
	public FpsStatusLineItem() {
		for (int i = 0; i < m_frames.length; i++)
			m_frames[i] = 0;
		avg = 0;
	}

	/**
	 * @param i_id
	 */
	public FpsStatusLineItem(String i_id) {
		super(i_id);
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see org.eclipse.jface.action.ContributionItem#fill(org.eclipse.swt.widgets.Composite)
	 */
	@Override
	public void fill(Composite i_parent) {

		Label sep = new Label(i_parent, SWT.SEPARATOR);
		m_label = new CLabel(i_parent, SWT.SHADOW_NONE);

		StatusLineLayoutData data = new StatusLineLayoutData();
		data.widthHint = getWidthHint(i_parent);
		m_label.setLayoutData(data);

		data = new StatusLineLayoutData();
		data.heightHint = getHeightHint(i_parent);
		sep.setLayoutData(data);

		updateCounter();
	}

	private int getHeightHint(Composite control) {

		if (m_fixedHeight < 0) {
			GC gc = new GC(control);
			gc.setFont(control.getFont());
			m_fixedHeight = gc.getFontMetrics().getHeight();
			gc.dispose();
		}
		return m_fixedHeight;
	}

	private int getWidthHint(Composite control) {

		if (m_fixedWidth < 0) {
			GC gc = new GC(control);
			gc.setFont(control.getFont());
			m_fixedWidth = gc.getFontMetrics().getAverageCharWidth()
					* CHAR_WIDTH;
			m_fixedWidth += INDENT * 2;
			gc.dispose();
		}
		return m_fixedWidth;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see de.feu.draw3d.RenderListener#renderPassFinished()
	 */
	public void renderPassFinished() {

		long time = System.currentTimeMillis();
		if (m_lastFrame == -1) {
			m_lastFrame = time;
			return;
		}

		long frameTime = time - m_lastFrame;
		m_lastFrame = time;

		if (frameTime <= TIMEOUT) {

			if (m_count < NUM_FRAMES)
				m_count++;

			avg -= m_frames[m_index];
			m_frames[m_index] = frameTime;
			avg += m_frames[m_index];

			m_index++;
			if (m_index >= NUM_FRAMES) {
				m_index = 0;
			}

		}

		updateCounter();
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see de.feu.draw3d.RenderListener#renderPassStarted()
	 */
	public void renderPassStarted() {

		// nothing to do
	}

	private synchronized void updateCounter() {

		long fps = 0;
		if (m_count > 0)
			fps = (long) (1000.0 / (avg / ((double) m_count)));
		//		System.out.println("i:"+m_index+", c="+m_count+", avg: " + avg);

		if (m_label != null && !m_label.isDisposed()) {
			Display display = m_label.getDisplay();

			m_label.setForeground(display
					.getSystemColor(SWT.COLOR_WIDGET_FOREGROUND));
			m_label.setText(fps + " FPS");
		}
	}
}
