/*
    TUIO Java backend - part of the reacTIVision project
    http://reactivision.sourceforge.net/

    Copyright (c) 2005-2009 Martin Kaltenbrunner <mkalten@iua.upf.edu>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package TUIO;

/**
 * The TuioTime class is a simple structure that is used to reprent the time that has elapsed since the session start.
 * The time is internally represented as seconds and fractions of microseconds which should be more than sufficient for gesture related timing requirements.
 * Therefore at the beginning of a typical TUIO session the static method initSession() will set the reference time for the session. 
 * Another important static method getSessionTime will return a TuioTime object representing the time elapsed since the session start.
 * The class also provides various addtional convience method, which allow some simple time arithmetics.
 *
 * @author Martin Kaltenbrunner
 * @version 1.4
 */ 
public class TuioTime {

    /**
     * the time since session start in seconds  
     */ 
    private long seconds = 0;
    /**
     * time fraction in microseconds  
     */ 
    private long  micro_seconds = 0;
    /**
     * the session start time in seconds
     */ 
    private static long start_seconds = 0;
    /**
     * start time fraction in microseconds
     */ 
    private static long start_micro_seconds = 0;
    
    /**
     * The default constructor takes no arguments and sets   
     * the Seconds and Microseconds attributes of the newly created TuioTime both to zero.
     */
    public TuioTime () {
        this.seconds = 0;
        this.micro_seconds = 0;
    }
    
    /**
     * This constructor takes the provided time represented in total Milliseconds 
     * and assigs this value to the newly created TuioTime.
     *
     * @param  msec  the total time in Millseconds
     */
    public TuioTime (long msec) {
        this.seconds = msec/1000;
        this.micro_seconds = 1000*(msec%1000);
    }
    
    /**
     * This constructor takes the provided time represented in Seconds and Microseconds   
     * and assigs these value to the newly created TuioTime.
     *
     * @param  sec  the total time in seconds
     * @param  usec    the microseconds time component
     */    
    public TuioTime (long sec, long usec) {
        this.seconds = sec;
        this.micro_seconds = usec;
    }

    /**
     * This constructor takes the provided TuioTime   
     * and assigs its Seconds and Microseconds values to the newly created TuioTime.
     *
     * @param  ttime  the TuioTime used to copy
     */    
    public TuioTime (TuioTime ttime) {
        this.seconds = ttime.getSeconds();
        this.micro_seconds = ttime.getMicroseconds();
    }
    
    /**
     * Sums the provided time value represented in total Microseconds to this TuioTime.
     *
     * @param  us    the total time to add in Microseconds
     * @return the sum of this TuioTime with the provided argument in microseconds
    */    
    public TuioTime add(long us) {
        long sec = seconds + us/1000000;
        long usec = micro_seconds + us%1000000;
        return new TuioTime(sec,usec);
    }

    /**
     * Sums the provided TuioTime to the private Seconds and Microseconds attributes.  
     *
     * @param  ttime    the TuioTime to add
     * @return the sum of this TuioTime with the provided TuioTime argument
     */
    public TuioTime add(TuioTime ttime) {
        long sec = seconds + ttime.getSeconds();
        long usec = micro_seconds + ttime.getMicroseconds();
        sec += usec/1000000;
        usec = usec%1000000;
        return new TuioTime(sec,usec);
    }

    /**
     * Subtracts the provided time represented in Microseconds from the private Seconds and Microseconds attributes.
     *
     * @param  us    the total time to subtract in Microseconds
     * @return the subtraction result of this TuioTime minus the provided time in Microseconds
     */        
    public TuioTime subtract(long us) {
        long sec = seconds - us/1000000;
        long usec = micro_seconds - us%1000000;
        
        if (usec<0) {
            usec += 1000000;
            sec--;
        }            
        
        return new TuioTime(sec,usec);
    }

    /**
     * Subtracts the provided TuioTime from the private Seconds and Microseconds attributes.
     *
     * @param  ttime    the TuioTime to subtract
     * @return the subtraction result of this TuioTime minus the provided TuioTime
     */    
    public TuioTime subtract(TuioTime ttime) {
        long sec = seconds - ttime.getSeconds();
        long usec = micro_seconds - ttime.getMicroseconds();
        
        if (usec<0) {
            usec += 1000000;
            sec--;
        }
        
        return new TuioTime(sec,usec);
    }

    /**
     * Takes a TuioTime argument and compares the provided TuioTime to the private Seconds and Microseconds attributes.
     *
     * @param  ttime    the TuioTime to compare
     * @return true if the two TuioTime have equal Seconds and Microseconds attributes
     */    
    public boolean equals(TuioTime ttime) {
        if ((seconds==ttime.getSeconds()) && (micro_seconds==ttime.getMicroseconds())) return true;
        else return false;
    }

    /**
     * Resets the seconds and micro_seconds attributes to zero.
     */
    public void reset() {
        seconds = 0;
        micro_seconds = 0;
    }

    /**
     * Returns the TuioTime Seconds component.
     * @return the TuioTime Seconds component
     */    
    public long getSeconds() {
        return seconds;
    }

    /**
     * Returns the TuioTime Microseconds component.
     * @return the TuioTime Microseconds component
     */    
    public long getMicroseconds() {
        return micro_seconds;
    }

    /**
     * Returns the total TuioTime in Milliseconds.
     * @return the total TuioTime in Milliseconds
     */    
    public long getTotalMilliseconds() {
        return seconds*1000+micro_seconds/1000;
    }

    /**
     * This static method globally resets the TUIO session time.
     */        
    public static void initSession() {
        TuioTime startTime = getSystemTime();
        start_seconds = startTime.getSeconds();
        start_micro_seconds = startTime.getMicroseconds();
    }

    /**
     * Returns the present TuioTime representing the time since session start.
     * @return the present TuioTime representing the time since session start
     */    
    public static TuioTime getSessionTime() {
        TuioTime sessionTime = getSystemTime().subtract(getStartTime());
        return sessionTime;
    
    }

    /**
     * Returns the absolut TuioTime representing the session start.
     * @return the absolut TuioTime representing the session start
     */    
    public static TuioTime getStartTime() {
        return new TuioTime(start_seconds,start_micro_seconds);
    }
        
    /**
     * Returns the absolut TuioTime representing the current system time.
     * @return the absolut TuioTime representing the current system time
     */    
    public static TuioTime getSystemTime() {
        long usec = System.nanoTime()/1000;
        return new TuioTime(usec/1000000,usec%1000000);
    }
}
