// BEGIN FLOCK GPL
//
// Copyright Flock Inc. 2005-2008
// http://flock.com
//
// This file may be used under the terms of the
// GNU General Public License Version 2 or later (the "GPL"),
// http://www.gnu.org/licenses/gpl.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// END FLOCK GPL

const CC = Components.classes;
const CI = Components.interfaces;
const CR = Components.results;
const CU = Components.utils;

var EXPORTED_SYMBOLS = ["FlockDateFormatter"];

const URI_DF_PROPERTIES =
  "chrome://flock/locale/common/flockDateFormatter.properties";

const MSECS_PER_DAY = 24 * 60 * 60 * 1000;

var FlockDateFormatter = {
  _initialized: false,

  _init: function FDF__init() {
    let sbs = CC["@mozilla.org/intl/stringbundle;1"]
              .getService(CI.nsIStringBundleService);
    this._bundle = sbs.createBundle(URI_DF_PROPERTIES);

    this._pureDateTimeFormat = this._bundle.GetStringFromName("time");
    this._reallyShortFormat = this._bundle.GetStringFromName("time.veryshort");
    this._mediumShortFormat = this._bundle.GetStringFromName("time.medshort");
    this._daysAgoFormat = this._bundle.GetStringFromName("daysAgo");
    this._hoursAgoFormat = this._bundle.GetStringFromName("hoursAgo");
    this._momentAgoFormat = this._bundle.GetStringFromName("momentAgo");
    this._minutesAgoFormat = this._bundle.GetStringFromName("minutesAgo");
    this._weeksAgoFormat = this._bundle.GetStringFromName("weeksAgo");
    this._yearsAgoFormat = this._bundle.GetStringFromName("yearsAgo");

    for each (let t in ["tomorrow", "today", "yesterday"]) {
      let tstr = this._bundle.GetStringFromName(t);

      this["_" + t + "String"] = tstr;

      this["_" + t + "DateTimeFormat"] =
        this._bundle.formatStringFromName("timeShort", [tstr], 1);
    }

    this._initialized = true;
  },

  getTimeString: function DF_getTimeString(aDate) {
    return aDate.toLocaleFormat("%I:%M %p").replace(/^0/, "");
  },

  getDateString: function DF_getDateString(aDate) {
    if (!this._initialized) {
      this._init();
    }

    let now = new Date();
    let todayDate = new Date(now.toDateString());
    let todayStartTime = todayDate.getTime();

    let inputTime = aDate.getTime();

    if (inputTime >= (todayStartTime + 2 * MSECS_PER_DAY)) {
      return aDate.toLocaleFormat("%A, %B %d, %Y").replace(" 0", " ");
    } else if (inputTime >= (todayStartTime + MSECS_PER_DAY)) {
      return this._tomorrowString;
    } else if (inputTime >= todayStartTime) {
      return this._todayString;
    } else if (inputTime >= (todayStartTime - MSECS_PER_DAY)) {
      return this._yesterdayString;
    } else {
      return aDate.toLocaleFormat("%A, %B %d, %Y").replace(" 0", " ");
    }
  },

  getDateTimeString: function DF_getDateTimeString(aDate) {
    let now = new Date();
    return this._getDateTimeStringHelper(aDate, now, this._pureDateTimeFormat);
  },

  getShortDateTimeString: function DF_getShortDateTimeString(aDate) {
    if (!this._initialized) {
      this._init();
    }

    let now = new Date();

    let format;
    if (aDate.getYear() == now.getYear()) {
      format = this._reallyShortFormat;
    } else {
      format = this._mediumShortFormat;
    }

    return this._getDateTimeStringHelper(aDate, now, format);
  },

  getFriendlyLastDate: function(aLastUpdated) {
    if (!this._initialized) {
      this._init();
    }

    let now = new Date();
    let updatedDate = now - aLastUpdated;

    let secondsSince = updatedDate / 1000;
    let minutesSince = secondsSince / 60;
    let hoursSince = minutesSince / 60;
    let daysSince = hoursSince / 24;
    let weeksSince = daysSince / 7;
    let yearsSince = daysSince / 365;

    if (yearsSince >= 1) {
      return yearsSince.toFixed(0) + this._yearsAgoFormat;
    } else if (daysSince > 13) {
      return weeksSince.toFixed(0) + this._weeksAgoFormat;
    } else if (daysSince >= 1) {
      return daysSince.toFixed(0) + this._daysAgoFormat;
    } else if (hoursSince >= 1) {
      return hoursSince.toFixed(0) + this._hoursAgoFormat;
    } else if (minutesSince >= 1) {
      return minutesSince.toFixed(0) + this._minutesAgoFormat;
    }

    // Invalid value check
    if (minutesSince < 0) {
      // Under/Overflow
      return "";
    }

    return this._momentAgoFormat;
  },

  getFormattedTime: function DF_getFormattedTime(aDate) {
    if (!this._initialized) {
      this._init();
    }

    let now = Date.now();
    let seconds = Math.round(now / 1000) - Math.round(aDate.getTime() / 1000);
    if (seconds < 60) {
      return this._bundle.GetStringFromName("lastUpdatePretty.aMomentAgo");
    }
    let minutes = Math.round(seconds / 60);
    if (minutes < 60) {
      if (minutes > 1) {
        return this._bundle.formatStringFromName("lastUpdatePretty.minutesAgo",
                                                 [minutes],
                                                 1);
      } else {
        return this._bundle.GetStringFromName("lastUpdatePretty.oneMinuteAgo");
      }
    }
    let hours = Math.round(minutes / 60);
    if (hours < 24) {
      if (hours > 1) {
        return this._bundle.formatStringFromName("lastUpdatePretty.hoursAgo",
                                                 [hours],
                                                 1);
      } else {
        return this._bundle.GetStringFromName("lastUpdatePretty.oneHourAgo");
      }
    }
    let days = Math.round(hours / 24);
    if (days < 7) {
      if (days > 1) {
        return this._bundle.formatStringFromName("lastUpdatePretty.daysAgo",
                                                 [days],
                                                 1);
      } else {
        return this._bundle.GetStringFromName("lastUpdatePretty.oneDayAgo");
      }
    } else {
      return this.getShortDateTimeString(aDate);
    }
  },

  _getDateTimeStringHelper: function DF_getDateTimeStringHelper(aDate,
                                                                aNow,
                                                                aFormat)
  {
    if (!this._initialized) {
      this._init();
    }

    let datetime;
    let todayDate = new Date(aNow.toDateString());
    let todayStartTime = todayDate.getTime();

    let inputTime = aDate.getTime();

    if (inputTime >= (todayStartTime + 2 * MSECS_PER_DAY)) {
      datetime = aDate.toLocaleFormat(format);
    } else if (inputTime >= (todayStartTime + MSECS_PER_DAY)) {
      datetime = aDate.toLocaleFormat(this._tomorrowDateTimeFormat);
    } else if (inputTime >= todayStartTime) {
      datetime = aDate.toLocaleFormat(this._todayDateTimeFormat);
    } else if (inputTime >= (todayStartTime - MSECS_PER_DAY)) {
      datetime = aDate.toLocaleFormat(this._yesterdayDateTimeFormat);
    } else {
      datetime = aDate.toLocaleFormat(aFormat);
    }

    return datetime.replace(/ 0/g, " ");
  }
};
