/*
 * CountDownTimer
 * by James G. Lombardo, dba The ByteShop.Net
 * Version 1.00
 * 
 * Copyright 2013 by The ByteShop.Net
 * License: MIT License
 *
 * The MIT License is simple and easy to understand and it places almost no 
 * restrictions on what you can do with a CountDownTimer software. You are free
 * to use this software in any projects as long as this header is left intact.
 *
 * The ByteShop.Net DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS[,][.] IN NO 
 * EVENT SHALL The BytesShop.Net BE LIABLE FOR ANY SPECIAL, INDIRECT OR 
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE 
 * OR PERFORMANCE OF THIS SOFTWARE.
 */

// create the root namespace and making sure we're not overwriting it
var ByteShopJs = ByteShopJs || {};

/* Create a general purpose namespace method
 * to allow us to create namespace a bit easier
 * 
 * Aknowledgements: thanks to Kenneth Truyers 
 * (@link http://www.kenneth-truyers.net/about-kenneth-truyers/) for this
 * sweet function
 */
ByteShopJs.createNS = function(namespace) {
    var nsparts = namespace.split(".");
    var parent = ByteShopJs;

    // we want to be able to include or exclude the root namespace 
    // So we strip it if it's in the namespace
    if (nsparts[0] === "ByteShopJs") {
        nsparts = nsparts.slice(1);
    }

    // loop through the parts and create 
    // a nested namespace if necessary
    for (var i = 0; i < nsparts.length; i++) {
        var partname = nsparts[i];
        // check if the current parent already has 
        // the namespace declared, if not create it
        if (typeof parent[partname] === "undefined") {
            parent[partname] = {};
        }
        // get a reference to the deepest element 
        // in the hierarchy so far
        parent = parent[partname];
    }
    // the parent is now completely constructed 
    // with empty namespaces and can be used.
    return parent;
};

ByteShopJs.createNS('ByteShopJs.util.datetime');

/**
 * CountDownTimer is a class that provides a dynamic count down display
 * from a starting time to zero.
 *
 * Example of how to use:
 * 
 *      var endDateInSecondsToGo = 20000;
 *      var displayElement = document.getElementById("myDisplayElement");
 *      var displayFormat = 'MEDIUM';
 *      var myCounter = new ByteShopJs.util.datetime.CountDownTimer();
 *      myCounter.startUsingSecondsToEndDate(endDateInSecondsToGo,displayElement,displayFormat);
 *    
 *      // Alternatively you can use the startUsingEndDate() function,
 *      // passing a Date object or formatted date string for the end date param
 * 
 *      var endDate = new Date(2013,7,1,0,0,0,0);
 *      var displayElement = document.getElementById("myDisplayElement");
 *      var displayFormat = 'SHORT';
 *      var myCounter = new ByteShopJs.util.datetime.CountDownTimer();
 *      myCounter.startUsingEndDate(endDate,displayElement,displayFormat);
 *
 * Display format options:
 *
 *    - An example of the MEDIUM (default) display format is: 2d 3h 40m 23s
 *    - An example of the LONG display format is: 
 *      2 days 3 hours 40 minutes 23 seconds
 *    - An example of the SHORT display format is: 02:03:40:23
 *    - The GRAPHIC option is the same as the SHORT option except that it
 *      puts the digits in colored boxes and adds a footer describing
 *      those digits. Note you need to use the sample stylesheet (main.css)
 *      or one of your own
 */
ByteShopJs.util.datetime.CountDownTimer = function() {
    var timeToGo;
    var startValue;
    var countDownTimer;
    var format = "MEDIUM";

    /**
     * Starts the count down timer. The timer will automatically be
     * stopped when the count down gets to zero.
     * @param {Date} endDate the end date for the counter
     * @param {Object} timeToGoElement the HTML element where the display 
     * text is set to the innerHTML of this element
     * @param {String} displayFormat a value of LONG, MEDIUM or SHORT 
     * indicating the display format style
     */
    var startUsingEndDate = function(endDate, timeToGoElement, displayFormat) {
        var today = new Date();
        startValue = Math.ceil((endDate - today)/1000)
        timeToGo = timeToGoElement;
        format = displayFormat;
        countDownTimer = window.setInterval(countDown, 1000);
    };

    /**
     * Starts the count down timer. The timer will automatically be
     * stopped when the count down gets to zero.
     * @param {Number} secondsToEndDate the number of seconds between now
     * and the end date
     * @param {Object} timeToGoElement the HTML element where the display 
     * text is set to the innerHTML of this element
     * @param {String} displayFormat a value of LONG, MEDIUM or SHORT 
     * indicating the display format style
     */
    var startUsingSecondsToEndDate = function(secondsToEndDate, timeToGoElement, displayFormat) {
        startValue = secondsToEndDate;
        timeToGo = timeToGoElement;
        format = displayFormat;
        countDownTimer = window.setInterval(countDown, 1000);
    };

    var stop = function() {
        window.clearInterval(countDownTimer);
    };

    var countDown = function() {
        if (startValue > 0) {
            startValue--;
            timeToGo.innerHTML = formatValue(startValue);
        } else {
            // if <= 0 the count down has ended
            timeToGo.innerHTML = formatValue(startValue);
        }
    };

    var formatValue = function(timeValue) {
        var fmt, days, hrs, mins, secs;
        var DAY_SEC = 60 * 60 * 24;
        var HR_SEC = 60 * 60;
        var MIN_SEC = 60;

        if (timeValue <= 0) {
            stop();
            return "Ended";
        }

        //  get days to go
        days = Math.floor(timeValue / DAY_SEC);
        timeValue -= (days * DAY_SEC);

        // get hours to go
        hrs = Math.floor(timeValue / HR_SEC);
        timeValue -= (hrs * HR_SEC);

        // get minutes to go
        mins = Math.floor(timeValue / MIN_SEC);
        timeValue -= (mins * MIN_SEC);

        // get seconds to go
        secs = timeValue;

        // now prepare format and return
        switch (format) {
            case "MEDIUM":
                fmt = "" + days + "d " + hrs + "h " + mins + "m " + secs + "s";
                break;

            case "LONG":
                if (days == 1) {
                    days = days + " day ";
                } else {
                    days = days + " days ";
                }
                if (hrs == 1) {
                    hrs = hrs + " hour ";
                } else {
                    hrs = hrs + " hours ";
                }
                if (days == 1) {
                    mins = mins + " minute ";
                } else {
                    mins = mins + " minutes ";
                }
                if (secs == 1) {
                    secs = secs + " second";
                } else {
                    secs = secs + " seconds";
                }
                fmt = "" + days + hrs + mins + secs;
                break;

            case "SHORT":
                if (days < 10)
                    days = "0" + days;
                if (hrs < 10)
                    hrs = "0" + hrs;
                if (mins < 10)
                    mins = "0" + mins;
                if (secs < 10)
                    secs = "0" + secs;
                fmt = "" + days + ":" + hrs + ":" + mins + ":" + secs;
                break;
                
            case "GRAPHIC":
                 if (days < 10)
                    days = "0" + days;
                if (hrs < 10)
                    hrs = "0" + hrs;
                if (mins < 10)
                    mins = "0" + mins;
                if (secs < 10)
                    secs = "0" + secs;
                fmt = "<div class='cd-timer-digit'>" + days + "</div>"
                      + "<div class='cd-timer-colon'>:</div>"
                      + "<div class='cd-timer-digit'>" + hrs + "</div>"
                      + "<div class='cd-timer-colon'>:</div>"
                      + "<div class='cd-timer-digit'>" + mins + "</div>"
                      + "<div class='cd-timer-colon'>:</div>"
                      + "<div class='cd-timer-digit'>" + secs + "</div>"
                      + "<br/>"
                      + "<div class='cd-timer-footer'>Days</div>"
                      + "<div class='cd-timer-footer'>Hrs</div>"
                      + "<div class='cd-timer-footer'>Min</div>"
                      + "<div class='cd-timer-footer'>Sec</div>";
               
                break;           

            default:
                fmt = "" + days + "d " + hrs + "h " + mins + "m " + secs + "s";
        }

        return fmt;
    };

    return {
        // Most properties and functions are private, but we'll expose this one.
        startUsingEndDate: startUsingEndDate,
        startUsingSecondsToEndDate: startUsingSecondsToEndDate
    };
};