/**
 * This class provides utilities work working with dates/time. Some of its main features:
 *
 *  * Provides integration layer for [Moment.js](http://momentjs.com/) library
 *  * Defines an abstraction layer for main date formats
 *
 *  **Formatting dates and time**
 *
 *  Usually when you develop an application you will have a requirement to format dates at least in three formats:
 *
 *  * plain date
 *  * time
 *  * date with time
 *
 *  MJR defines standard formats used in Europe for all of the aformentioned combinations and this is how you can use
 *  them:
 *
 *      var date = new Date();
 *
 *      Ext.Date.format(date, MFC.Date.patterns.ext.date);
 *      Ext.Date.format(date, MFC.Date.patterns.ext.time);
 *      Ext.Date.format(date, MFC.Date.patterns.ext.datetime);
 *
 * The good thing about using central place for keeping formats is that later you can override those formats using
 * standard JavaScript prototype and dates will be formatted differently in all places.
 *
 * **Using MomentJs**
 *
 * When you have an object which stores a reference to moment then you can use MFC.Date.format function to format
 * dates:
 *
 *     var now = MFC.Date.moment();
 *
 *     MFC.Date.format(now, 'date');
 *     MFC.Date.format(now, 'time');
 *     MFC.Date.format(now, 'datetime');
 *
 *  Results of using this approach and using native JavaScript Date in combination with Ext.date.format and this one
 *  illustrated here will be the same in this specific case.
 *
 * @class MFC.Date
 */
Ext.define('MFC.Date', {});

/**
 * Some sample data formats.
 *
 * Available options are:
 *
 *  * MFC.Date.patterns.ISO8601
 *  * MFC.Date.patterns.ISO8601Long
 *  * MFC.Date.patterns.ISO8601Short
 *  * MFC.Date.patterns.ShortDate
 *  * MFC.Date.patterns.LongDate
 *  * MFC.Date.patterns.FullDateTime
 *  * MFC.Date.patterns.MonthDay
 *  * MFC.Date.patterns.ShortTime
 *  * MFC.Date.patterns.LongTime
 *  * MFC.Date.patterns.SortableDateTime
 *  * MFC.Date.patterns.UniversalSortableDateTime
 *  * MFC.Date.patterns.YearMonth
 *
 * @property
 */
MFC.Date.patterns = {
    // these are for standard javascript's Date object
    ISO8601: "Y-m-d H:i",
    ISO8601Long: "Y-m-d H:i:s",
    ISO8601Short: "Y-m-d",
    ShortDate: "n/j/Y",
    LongDate: "l, F d, Y",
    FullDateTime: "l, F d, Y g:i:s A",
    MonthDay: "F d",
    ShortTime: "g:i A",
    LongTime: "g:i:s A",
    SortableDateTime: "Y-m-d\\TH:i:s",
    UniversalSortableDateTime: "Y-m-d H:i:sO",
    YearMonth: "F, Y",

    // this is a central place to override if you want to change the way how dates are formatted
    // first block defines formats for MomentJs library, second one for ExtJs
    moment: {
        time: 'LT',
        date: 'L',
        datetime: 'L LT'
    },
    ext: {
        date: (new Ext.form.field.Date()).format,
        time: (new Ext.form.field.Time()).format,
        datetime: (new Ext.form.field.Date()).format + ' ' + (new Ext.form.field.Time()).format
    }
};

if (typeof moment == 'undefined') {
    (function (undefined) {
        var moment,
            global = this;

        moment = function() {
            alert('Moment.js is not defined!');
        };

        global['moment'] = moment;
    }).call(this);
}

/**
 * Returns instance of "moment" object or shows error message using "alert" that "moment" library is not found.
 *
 * @method moment
 * @return {Object} Instance of "moment" object
 */
MFC.Date.moment = function() {
    var args = Array.prototype.slice.call(arguments);

    // workaround for "Invalid date"
    if (1 == args.length && 'string' == typeof args[0] && !moment(args[0]).isValid()) {
        var date = new Date(args[0]);
        if (!isNaN(date)) {
            args[0] = date;
        }
    }

    return moment.apply(null, args);
};
for (var key in moment) {
    if (!!moment[key]) {
        MFC.Date.moment[key] = moment[key];
    }
}

/**
 * You can use this method when you don't care about exact date, time, datetime format. Later those
 * can be overridden by locale specific to a user.
 *
 * @method format
 * @param {String|moment} momentOrStringDate
 * @param {String} type  Can be either of these: date, time, datetime
 * @return {String}
 */
MFC.Date.format = function(momentOrStringDate, type) {
    if (!Ext.Array.contains(Ext.Object.getKeys(MFC.Date.patterns.moment), type)) {
        throw 'MFC.date.format(moment, type): Only date, time and datetime can be given as "type" argument!';
    }

    var moment = MFC.Date.moment.isMoment(momentOrStringDate) ? momentOrStringDate : MFC.Date.moment(momentOrStringDate);

    return moment.format(MFC.Date.patterns.moment[type]);
};