package org.studiorailgun.schedule;

/**
 * A time in the simulation timeline
 */
public class Time implements Comparable<Time> {
    
    /**
     * Number of months in a year
     */
    static final int MONTHS_IN_YEAR = 12;

    /**
     * Number of days in a month
     */
    static final int DAYS_IN_MONTH = 30;

    /**
     * Number of hours in a day
     */
    static final int HOURS_IN_DAY = 24;

    /**
     * Number of minutes in an hour
     */
    static final int MINUTES_IN_HOUR = 60;

    /**
     * Number of seconds in a minute
     */
    static final int SECONDS_IN_MINUTE = 60;

    /**
     * The value of the time
     */
    long value;

    /**
     * Creates a time with a raw value
     * @param value The value
     */
    public Time(long value){
        this.value = value;
    }

    /**
     * Creates a time at a given year, month, and day
     * @param year The year
     * @param month The month
     * @param day The day
     * @param hour The hour
     * @param minute The minute
     * @param second The second
     */
    public Time(int year, int month, int day, int hour, int minute, int second){
        this.value = Time.getOffset(year, month, day, hour, minute, second);
    }

    /**
     * Gets a time offset from this time
     * @param year The number of years to offset
     * @param month The number of months to offset
     * @param day The number of days to offset
     * @param hour The number of hours to offset
     * @param minute The number of minutes to offset
     * @param second The number of seconds to offset
     * @return The time containing the offset value
     */
    public Time offset(int year, int month, int day, int hour, int minute, int second){
        Time rVal = new Time(this.value);
        rVal.value = rVal.value + Time.getOffset(year, month, day, hour, minute, second);
        return rVal;
    }

    /**
     * Gets the year of this time
     * @return The year
     */
    public int year(){
        return (int)this.value / (SECONDS_IN_MINUTE * MINUTES_IN_HOUR * HOURS_IN_DAY * DAYS_IN_MONTH * MONTHS_IN_YEAR);
    }

    /**
     * Gets the month of this time
     * @return The month
     */
    public int month(){
        return (int)this.value / (SECONDS_IN_MINUTE * MINUTES_IN_HOUR * HOURS_IN_DAY * DAYS_IN_MONTH);
    }

    /**
     * Gets the day of this time
     * @return The day
     */
    public int day(){
        return (int)this.value / (SECONDS_IN_MINUTE * MINUTES_IN_HOUR * HOURS_IN_DAY);
    }

    /**
     * Gets the hour of this time
     * @return The hour
     */
    public int hour(){
        return (int)this.value / (SECONDS_IN_MINUTE * MINUTES_IN_HOUR);
    }

    /**
     * Gets the minute of this time
     * @return The minute
     */
    public int minute(){
        return (int)this.value / SECONDS_IN_MINUTE;
    }

    /**
     * Gets the second of this time
     * @return The second
     */
    public int second(){
        return (int)this.value % SECONDS_IN_MINUTE;
    }

    /**
     * Gets an offset given a set of legible time values
     * @param year The number of years
     * @param month The number of months
     * @param day The number of days
     * @param hour The number of hours
     * @param minute The number of minutes
     * @param second The number of seconds
     * @return The offset
     */
    private static long getOffset(int year, int month, int day, int hour, int minute, int second){
        return
        second +
        minute * SECONDS_IN_MINUTE +
        hour * SECONDS_IN_MINUTE * MINUTES_IN_HOUR +
        day * SECONDS_IN_MINUTE * MINUTES_IN_HOUR * HOURS_IN_DAY +
        month * SECONDS_IN_MINUTE * MINUTES_IN_HOUR * HOURS_IN_DAY * DAYS_IN_MONTH +
        year * SECONDS_IN_MINUTE * MINUTES_IN_HOUR * HOURS_IN_DAY * DAYS_IN_MONTH * MONTHS_IN_YEAR
        ;
    }

    @Override
    public int compareTo(Time other) {
        return (int)(this.value - other.value);
    }

}
