pulp.Modules['date.extension'] = true;

(function() {

  var $D = pulp.date.getInstance;
  
  /**
   * Date patterns for Date instance methods
   *
   * @requires base
   * @requires date
   */
  pulp.base.extend(pulp.date.patterns, /** @scope pulp.date.patterns */{
    // 5 months ago, 2 hours ago, etc.
    ago:
    function (str) {
      var match = str.match( /(a|[\d.]+)\s+(year|month|week|day|hour|minute|second)s?\s+ago/i );
      if (match) {
        return $D().add(-1 * (parseFloat(match[1]) || 1), match[2]);
      }
    },
    // 2 weeks after today, 3 months before 3-5-2008, 2 hours from now, etc.
    after:
    function (str) {
      var match = str.match( /(a|[\d.]+)\s+(year|month|week|day|hour|minute|second)s?\s+(before|from|after|following)\s+(.+)/i );
      if (match) {
        var fromDate = $D(match[4]);
        if (fromDate instanceof pulp.date) {
          return fromDate.add((match[3].toLowerCase() == 'before' ? -1 : 1) * (parseFloat(match[1]) || 1), match[2]);
        }
      }
    },
    // today, tomorrow, yesterday
    today:
    function (str) {
      var match = str.match( /^(tod|now|tom|yes)/i );
      if (match) {
        switch (match[1].toLowerCase()) {
          case 'tod':
          case 'now':
            return $D();
          case 'tom':
            return $D().add(1, 'day');
          case 'yes':
            return $D().add(-1, 'day');
        }
      }
    },
    // next month, last month, next tuesday, etc.
    next:
    function (str) {
      var match = str.match( /(this|next|last)\s+(.{3,20})/i );
      if (match) {
        var now = $D();
        var multiplier = match[1].toLowerCase() == 'last' ? -1 : 1;
        if ((/^month|week|year$/i).test(match[2])) {
          return now.add(multiplier, match[2].toLowerCase());
        }
        var monthOrDay = match[2].slice(0, 3).toLowerCase();
        var months = pulp.date.ABBR_MONTHNAMES;
        for (var i = 0; i < months.length; i++) {
          if ((new RegExp('^' + months[i], 'i')).test(monthOrDay)) {
            do {
              now.add(multiplier, 'month');
            } while (now.getMonth() != i);
            return now;
          }
        }
        var days = pulp.date.ABBR_DAYNAMES;
        for (i = 0; i < days.length; i++) {
          if ((new RegExp('^' + days[i], 'i')).test(monthOrDay)) {
            do {
              now.add(multiplier, 'day');
            } while (now.getDay() != i);
            return now;
          }
        }      
      }
    }
  });
})();


  
pulp.date.phpFormat = {
  //
  // 2-part regex matcher for format codes
  //
  // first match must be the character before the code (to account for escaping)
  // second match must be the format code character(s)
  //
  matcher: /(^|[^\\])([a-z])/i,

  codes: {
    // year
    Y: 'FullYear',
    y: 'ShortYear.2',
    // month
    m: 'MonthNumber.2',
    n: 'MonthNumber',
    M: 'AbbrMonthName',
    F: 'MonthName',
    // day
    d: 'Date.2',
    j: 'Date',
    D: 'AbbrDayName',
    l: 'DayName', // lowercase "L"
    S: 'DayOrdinal',
    w: 'Day',
    // hours
    H: 'Hours.2',
    h: 'Hours',
    G: 'Hours12.2',
    g: 'Hours12',
    a: 'AmPm',
    // minutes
    i: 'Minutes.2',
    // seconds
    s: 'Seconds.2',
    U: 'Unix',
    // timezone
    p: 'TimezoneOffset',
    e: 'TimezoneName',
    Z: 'GmtOffset'  
  },
  //
  // shortcuts that will be translated into their longer version
  //
  // be sure that format shortcuts do not refer to themselves: this will cause an infinite loop
  //
  shortcuts: {
    c: 'Y-m-d\TH:i:s', // ISO 8601
    r: 'D, j d M Y H:i:s p' // RFC 2822
  }
};

pulp.date.addFormatter('phpFormat', 'Y-m-d');


pulp.date.sqlFormat = {
  
  //
  // 2-part regex matcher for format codes
  //
  // first match must be the character before the code (to account for escaping)
  // second match must be the format code character(s)
  //
  matcher: /()(h?h12|h?h24|mi|am|pm|([a-z])\3{0,4})/i,

  codes: {
    // year
    yyyy: 'FullYear',
    yy: 'ShortYear.2',
    // month
    mm: 'MonthNumber.2',
    m: 'MonthNumber',
    mmm: 'AbbrMonthName',
    mmmm: 'MonthName',
    // day
    dd: 'Date.2',
    d: 'Date',
    ddd: 'AbbrDayName',
    dddd: 'DayName',
    w: 'Day',
    // hours
    hh24: 'Hours.2',
    h24: 'Hours',
    hh12: 'Hours12.2',
    h12: 'Hours12',
    am: 'AmPm',
    pm: 'AmPm',
    // minutes
    mi: 'Minutes.2',
    // seconds
    ss: 'Seconds.2'
  },
  //
  // shortcuts that will be translated into their longer version
  //
  // be sure that format shortcuts do not refer to themselves: this will cause an infinite loop
  //
  shortcuts: {}
};

// add uppercase versions of each code
// (Enumerate keys to avoid IE bug that causes infinite loop while adding keys to the object you are iterating) 
pulp.base.each('yyyy yy mm m mmm mmmm dd d ddd dddd w hh24 h24 hh12 h12 am pm mi ss', function(code) {
  pulp.date.sqlFormat.codes[code.toUpperCase()] = pulp.date.sqlFormat.codes[code];
});

pulp.date.addFormatter('sqlFormat', 'yyyy-mm-dd hh24:mi:ss');