/* NEEDS: format-helpers.js
 *        number-utils.js  */

/* constants first */
var DU_INCLUDE_DAYS = 1;
var DU_INCLUDE_HOURS = DU_INCLUDE_DAYS * 2;
var DU_INCLUDE_MINUTES = DU_INCLUDE_HOURS * 2;
var DU_INCLUDE_SECONDS = DU_INCLUDE_MINUTES * 2;
var DU_INCLUDE_MILLIS = DU_INCLUDE_SECONDS * 2;

var MILLIS_PER_SECOND = 1000;
var SECONDS_PER_MINUTE = 60;
var MINUTES_PER_HOUR = 60;
var HOURS_PER_DAY = 24;

/* writes a due notice */
function documentDue (whatDoc, year, month, day)
{    
    var text = whatDoc;
    
    try
    {
        var dur = getTimeToString (year, month, day, 
                                   17, 0, 0, 0, DU_INCLUDE_DAYS);
        text += dur;
    }
    catch (err)
    {
        text += " OVERDUE!!!";
    }
    
    // print the notice
    writeEmptyLine ();
    writeBanner (text, "due-date", "", "", "");
}

/* selfupdating clock */
function startClock (clockID, timeOut,
                     documentDue,
                     year, month, day,
                     hour, minute, second, milli)
{
    var newTime = documentDueClock (documentDue,
                                    year, month, day,
                                    hour, minute, second, milli);
    var f = "";
    f += 'startClock("';
    f += clockID;
    f += '", ';
    f += timeOut;
    f += ', "';
    f += documentDue;
    f += '", ';
    f += year;
    f += ', ';
    f += month;
    f += ', ';
    f += day;
    f += ', ';
    f += hour;
    f += ', ';
    f += minute;
    f += ', ';
    f += second;
    f += ', ';
    f += milli;
    f += ')'; 
    
    document.getElementById(clockID).innerHTML = newTime;
    
    var t = setTimeout (f, timeOut); 
}

/* countdown clock */
function documentDueClock (documentDue, year, month, day, 
                           hour, minute, second, milli)
{
    var text = documentDue;
    try 
    {
        var include = DU_INCLUDE_DAYS | DU_INCLUDE_HOURS |
                      DU_INCLUDE_MINUTES | DU_INCLUDE_SECONDS;
        var timeDiff = getTimeToString (year, month, day, hour,
                                        minute, second, milli,
                                        include);
        text += timeDiff;
    }
    catch (err)
    {
        // getTimeTo will throw if the specified date already occurred
        // handle the excpetion here
        text += err;
        text += " OVERDUE!!!";
    }
    
    return text;
}

function documentDueBanner (documentDue, year, month, day,
                           hour, minute, second, milli) 
{
    var text = documentDueClock (documentDue, year, month, day,
                                 hour, minute, second, milli);
    writeEmptyLine ();
    writeBanner (text, "due-date", "due-date", "due-date", "");
}

/* returns a Date variable telling how much time is left to 
 * before the specific date/time */
function getTimeToString (year, month, day, hour,  
                          minute, second, milli, include)
{    
    // due date
    var dueDate = new Date ();
    dueDate.setFullYear (year);
    dueDate.setMonth (month - 1); // convert to JS 0-11 numbering of months
    dueDate.setDate (day);
    dueDate.setHours (hour);
    dueDate.setMinutes (minute);
    dueDate.setSeconds (second);
    dueDate.setMilliseconds (milli);
    
    // now date
    var nowDate = new Date ();
    
    // compute the difference 
    var duems = dueDate.getTime ();
    var nowms = nowDate.getTime ();
    var diffms = duems - nowms;
    
    // convert back to Date object
    var rtValue = "";
    if (diffms > 0)
    {
        rtValue += getTimeString (diffms, include);
    } 
    else
    {
        throw ("Past due");
    }

    return rtValue;
}

/* converts time structure into a duration string */
function getTimeString (millis, include)
{
    // compute components
    var days = castToInt (millis / (MILLIS_PER_SECOND * 
                                    SECONDS_PER_MINUTE *
                                    MINUTES_PER_HOUR *
                                    HOURS_PER_DAY));
        
    millis -= (days * MILLIS_PER_SECOND
                    * SECONDS_PER_MINUTE 
                    * MINUTES_PER_HOUR 
                    * HOURS_PER_DAY);
                  
    var hours = castToInt (millis / (MILLIS_PER_SECOND *
                                     SECONDS_PER_MINUTE *
                                     MINUTES_PER_HOUR));
    
    millis -= (hours * MILLIS_PER_SECOND 
                     * SECONDS_PER_MINUTE 
                     * MINUTES_PER_HOUR);
                    
    var minutes = castToInt (millis / (MILLIS_PER_SECOND *
                                       SECONDS_PER_MINUTE));
                                       
    millis -= (minutes * MILLIS_PER_SECOND 
                       * SECONDS_PER_MINUTE);
                       
    seconds = castToInt (millis / MILLIS_PER_SECOND);
    millis = millis - seconds * MILLIS_PER_SECOND;
    
    // convert to a nice string
    var rtValue = "";
    if (include & DU_INCLUDE_DAYS)
    {
        rtValue += days;
        rtValue += " day";
        rtValue += (days != 1) ? "s" : "";
    }
    
    if (include & DU_INCLUDE_HOURS)
    {
        rtValue += (rtValue.length) ? ", " : "";
        rtValue += hours;
        rtValue += " hour";
        rtValue += (hours != 1) ? "s" : "";
    }
    
    if (include & DU_INCLUDE_MINUTES)
    {
        rtValue += (rtValue.length) ? ", " : "";
        rtValue += minutes;
        rtValue += " minute";
        rtValue += (minutes != 1) ? "s" : "";
    }
    
    if (include & DU_INCLUDE_SECONDS)
    {
        rtValue += (rtValue.length) ? ", " : "";
        rtValue += seconds;
        rtValue += (include & DU_INCLUDE_MILLIS) ? "." : " second";
        rtValue += (seconds != 1) ? "s" : "";
    }
    
    if (include & DU_INCLUDE_MILLIS)
    {
        rtValue += millis;
        rtValue += " seconds";
    } 
    
    return rtValue; 
}

// compute the time remaining (return only the number of largest 
// units remaining)
function timeRemaining (eventDate)
{
    var eTime = eventDate.getTime ();
    var now = new Date ();
    var cTime = now.getTime ();
    var rtValue = "----"; // default result
    
    if (cTime >= eTime)
    {
        // do nothing, take the default result
    }
    else
    {
        var millis = eTime - cTime;
        var days = castToInt (millis / (MILLIS_PER_SECOND * 
                                        SECONDS_PER_MINUTE *
                                        MINUTES_PER_HOUR *
                                        HOURS_PER_DAY));
            
        millis -= (days * MILLIS_PER_SECOND
                        * SECONDS_PER_MINUTE 
                        * MINUTES_PER_HOUR 
                        * HOURS_PER_DAY);
                      
        var hours = castToInt (millis / (MILLIS_PER_SECOND *
                                         SECONDS_PER_MINUTE *
                                         MINUTES_PER_HOUR));
        
        millis -= (hours * MILLIS_PER_SECOND 
                         * SECONDS_PER_MINUTE 
                         * MINUTES_PER_HOUR);
                        
        var minutes = castToInt (millis / (MILLIS_PER_SECOND *
                                           SECONDS_PER_MINUTE));
                                           
        millis -= (minutes * MILLIS_PER_SECOND 
                           * SECONDS_PER_MINUTE);
                           
        seconds = castToInt (millis / MILLIS_PER_SECOND);
        millis = millis - seconds * MILLIS_PER_SECOND;
        
        if (days > 0)
        {
            rtValue = "" + days + "d" + 
                      ((hours > 0 || minutes > 0 || 
                        seconds > 0 || millis > 0) ?
                      "+" : "");    
        }    
        else if (days == 0 && hours > 0)
        {
            rtValue = ""+ hours + "h" +
                      ((minutes > 0 || seconds > 00 || millis > 0) ?
                      "+" : "");
        }
        else if (days == 0 && hours == 0 && minutes > 0)
        {
            rtValue = "" + minutes + "m" + 
                      ((seconds > 0 || millis > 0) ?
                      "+" : "");
        }
        else if (days == 0 && hours == 0 && minutes == 0 && seconds > 0)
        {
            rtValue = "" + seconds + "s" + 
                     ((millis > 0) ? "+" : "");
        }
        else 
        {
            // rtValue = "----";
        }
    }
    
    return rtValue;
}
