/* dateImpl.ts

	Purpose:
		date with timezone information
	Description:
		Methods defined in DateImpl object is pretty similar to js Date object.
		The difference is there is timezone information in DateImpl object,
		but isn't in js Date object.
	History:
		Tue Dec 5 12:35:34     2017, Created by bobpeng

Copyright (C) 2017 Potix Corporation. All Rights Reserved.

This program is distributed under LGPL Version 2.1 in the hope that
it will be useful, but WITHOUT ANY WARRANTY.
*/
window.Dates = {
  newInstance: function newInstance(param, tz) {
    var m;
    if (tz) tz = parseTzId(tz);else tz = zk.mm.tz.guess();

    if (arguments.length == 0) {
      m = zk.mm();
    } else if (typeof param == 'number') {
      m = zk.mm(param);
    } else if (param instanceof DateImpl) {
      m = zk.mm(param._moment);
      tz = param._timezone;
    } else if (param instanceof Array) {
      // [y, m, d, hr, min, sec, millisec]
      var d = new Date(Date.UTC.apply(null, param));
      if (param[0] < 100) d.setUTCFullYear(param[0]); //ZK-4292: incorrect year when the year is less than 100

      m = zk.mm.tz([d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds()], tz);
    }

    return new DateImpl(m, tz);
  }
};

window.DateImpl = function (m, tz) {
  this._moment = m;
  this._timezone = tz;
};

function parseTzId(id) {
  if (/^GMT\+([0]\d|[1][0-2]):[0]{2}$/i.test(id)) {
    return 'Etc/GMT-' + parseInt(id.substring(4, 6));
  } else if (/^GMT-([0]\d|[1][0-4]):[0]{2}$/i.test(id)) {
    return 'Etc/GMT+' + parseInt(id.substring(4, 6));
  } else {
    return id;
  }
}

DateImpl.prototype = {
  tz: function tz(v) {
    if (v) this._timezone = parseTzId(v);
    return this;
  },
  _getTzMoment: function _getTzMoment() {
    return this._moment.tz(this._timezone);
  },
  _getUTCMoment: function _getUTCMoment() {
    return this._moment.tz('UTC');
  },
  getTimeZone: function getTimeZone() {
    return this._timezone;
  },
  getDate: function getDate() {
    return this._getTzMoment().date();
  },
  getDay: function getDay() {
    return this._getTzMoment().day();
  },
  getFullYear: function getFullYear() {
    return this._getTzMoment().year();
  },
  getHours: function getHours() {
    return this._getTzMoment().hour();
  },
  getMilliseconds: function getMilliseconds() {
    return this._getTzMoment().millisecond();
  },
  getMinutes: function getMinutes() {
    return this._getTzMoment().minute();
  },
  getMonth: function getMonth() {
    return this._getTzMoment().month();
  },
  getSeconds: function getSeconds() {
    return this._getTzMoment().second();
  },
  getTime: function getTime() {
    return this._moment.valueOf();
  },
  getTimezoneOffset: function getTimezoneOffset() {
    return -this._getTzMoment().utcOffset();
  },
  getUTCDate: function getUTCDate() {
    return this._getUTCMoment().date();
  },
  getUTCDay: function getUTCDay() {
    return this._getUTCMoment().day();
  },
  getUTCFullYear: function getUTCFullYear() {
    return this._getUTCMoment().year();
  },
  getUTCHours: function getUTCHours() {
    return this._getUTCMoment().hour();
  },
  getUTCMilliseconds: function getUTCMilliseconds() {
    return this._getUTCMoment().millisecond();
  },
  getUTCMinutes: function getUTCMinutes() {
    return this._getUTCMoment().minute();
  },
  getUTCMonth: function getUTCMonth() {
    return this._getUTCMoment().month();
  },
  getUTCSeconds: function getUTCSeconds() {
    return this._getUTCMoment().second();
  },
  getYear: function getYear() {
    return this._getTzMoment().year() - 1900;
  },
  setDate: function setDate(v) {
    return this._getTzMoment().date(v).valueOf();
  },
  setFullYear: function setFullYear(y, m, d) {
    var mt = this._getTzMoment();

    mt.year(y);

    if (m != null) {
      mt.month(m);
      if (d != null) mt.date(d);
    }

    return mt.valueOf();
  },
  setHours: function setHours(hr, min, sec, msec) {
    var mt = this._getTzMoment();

    mt.hour(hr);

    if (min != null) {
      mt.minute(min);

      if (sec != null) {
        mt.second(sec);
        if (msec != null) mt.millisecond(msec);
      }
    }

    return mt.valueOf();
  },
  setMilliseconds: function setMilliseconds(v) {
    return this._getTzMoment().millisecond(v).valueOf();
  },
  setMinutes: function setMinutes(v) {
    return this._getTzMoment().minute(v).valueOf();
  },
  setMonth: function setMonth(v) {
    return this._getTzMoment().month(v).valueOf();
  },
  setSeconds: function setSeconds(v) {
    return this._getTzMoment().second(v).valueOf();
  },
  setTime: function setTime(v) {
    this._moment = zk.mm(v);
    return this._moment.valueOf();
  },
  setUTCDate: function setUTCDate(v) {
    return this._getUTCMoment().date(v).valueOf();
  },
  setUTCFullYear: function setUTCFullYear(v) {
    return this._getUTCMoment().year(v).valueOf();
  },
  setUTCHours: function setUTCHours(v) {
    return this._getUTCMoment().hour(v).valueOf();
  },
  setUTCMilliseconds: function setUTCMilliseconds(v) {
    return this._getUTCMoment().millisecond(v).valueOf();
  },
  setUTCMinutes: function setUTCMinutes(v) {
    return this._getUTCMoment().minute(v).valueOf();
  },
  setUTCMonth: function setUTCMonth(v) {
    return this._getUTCMoment().month(v).valueOf();
  },
  setUTCSeconds: function setUTCSeconds(v) {
    return this._getUTCMoment().second(v).valueOf();
  },
  setYear: function setYear(v) {
    return this._getTzMoment().year(v).valueOf();
  },
  toString: function toString() {
    return this._getTzMoment().toString();
  },
  valueOf: function valueOf() {
    return this._moment.valueOf();
  },
  toDateString: function toDateString() {
    return '';
  },
  toTimeString: function toTimeString() {
    return '';
  },
  toLocaleDateString: function toLocaleDateString() {
    return '';
  },
  toLocaleTimeString: function toLocaleTimeString() {
    return '';
  },
  toUTCString: function toUTCString() {
    return '';
  },
  toISOString: function toISOString() {
    return '';
  },
  toJSON: function toJSON(key) {
    return '';
  }
};