/*
 * $Id$
 *
 * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package com.sun.javatest.exec;

import java.awt.EventQueue;

import javax.accessibility.AccessibleContext;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JTextField;

import com.sun.javatest.tool.UIFactory;
import com.sun.javatest.util.I18NResourceBundle;

class ElapsedTimeMonitor extends Monitor implements MonitorState.Observer {
    ElapsedTimeMonitor(MonitorState ms, UIFactory uif) {
	super(ms, uif);
	ms.addObserver(this);
    }

    public String getSmallMonitorName() {
	return uif.getI18NString("et.sm.Name");
    }

    public Icon getSmallMonitorIcon() {
	return null;
    }

    public JComponent getSmallMonitor() {
	if (smTimer == null)
	    smTimer = new SmallTimer(uif, state);

	if (isRunning)
	    smTimer.start();
	else
	    smTimer.update();

	return smTimer;
    }

    public String getLargeMonitorName() {
	return uif.getI18NString("et.lg.Name");
    }

    public Icon getLargeMonitorIcon() {
	return null;
    }

    public JComponent getLargeMonitor() {
	return null;
    }

    // MonitorState.Observer
    public void starting() {
	isRunning = true;

	if (smTimer != null)
	    smTimer.start();
    }

    public void postProcessing() {
	if (smTimer != null)
	    smTimer.stop();
    }

    public void stopping() {
    }

    public void finished(boolean allOk) {
	isRunning = false;
	stopAll();
    }

    /**
     * Stop all active subthreads associated with a running harness.
     */
    private void stopAll() {
	if (smTimer != null)
	    smTimer.stop();
    }

    /**
     * Current instance of the small timer.
     */
    private SmallTimer smTimer;
    private ThreadGroup activeThreads = new ThreadGroup("elapsed time monitors");
    private boolean isRunning;
    private static I18NResourceBundle i18n;

    /**
     * Message strip sized timer.  Should be reusable using start and stop.
     */
    static class SmallTimer extends JTextField {
	SmallTimer(UIFactory uif, MonitorState ms) {
	    super("et.sm");
	    this.state = ms;
	    this.uif = uif;

	    setHorizontalAlignment(JTextField.LEFT);
	    setOpaque(false);
	    setEnabled(true);
	    setVisible(true);
	    setEditable(false);
	    setBorder(BorderFactory.createEmptyBorder());
	    /*
	    prefix = uif.getI18NString("et.sm.prefix");
	    setText(prefix + "00:00:00");
	    */
	    setText("00:00:00");
	    uif.setToolTip(this, "et.sm");
	    AccessibleContext ac = getAccessibleContext();
	    ac.setAccessibleName(uif.getI18NString("et.sm.name"));

	    update();
	}

	public void start() {
	    myThread = new Thread() {
		public void run() {
		    while(myThread == currentThread()) {
			try {
			    synchronized (myThread) {
				myThread.wait(1000);
				update();
			    }
			}
			catch(InterruptedException e) {
			}
		    }	// while

		    // one last update of the time
		    update();
		}
	    };	// Thread()

	    // user will notice this, so set a higher priority
	    myThread.setPriority(Thread.MIN_PRIORITY + 3);
	    myThread.start();
	}

	public void stop() {
	    myThread = null;
	}

	private void update() {
	    if (!EventQueue.isDispatchThread())
		EventQueue.invokeLater(new BranchPanel.TextUpdater(this,
				       millisToString(state.getElapsedTime()), uif));
	    else
		setText(millisToString(state.getElapsedTime()));
	}

	private String prefix;
	private MonitorState state;
	private UIFactory uif;
	private volatile Thread myThread;
    }

    /**
     * Converts time in millisections to localized HH:MM:SS (or equivalent)
     * string.
     */
    static final String millisToString(long millis) {
	// lazy init.
	if (i18n == null)
	    i18n = I18NResourceBundle.getBundleForClass(ElapsedTimeMonitor.class);

	int seconds = (int)((millis / 1000) % 60);
	int minutes = (int)((millis / 60000) % 60);
	int hours = (int)(millis / 3600000);

	String h, m, s;

	if (hours < 10)
	    h = "0" + Integer.toString(hours);
	else
	    h = Integer.toString(hours);

	if (minutes < 10)
	    m = "0" + Integer.toString(minutes);
	else
	    m = Integer.toString(minutes);

	if (seconds < 10)
	    s = "0" + Integer.toString(seconds);
	else
	    s = Integer.toString(seconds);

	String[] args = {h, m, s};

	return i18n.getString("etm.hms", args);
    }
}


