/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

if (!Array.prototype.mergeWithPairedKey) {
  var script = document.createElement("script");  // create a script DOM node
  script.src = 'js/utils.js';  // set its src to the provided URL

  document.head.appendChild(script);
}

var MonthArry = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
var MonthFullArry = ["January", "Febuary", "March", "April", "May", "June", "July", "August", "Septempber", "October", "November", "December"];

var FullMonthName = MonthFullArry.mergeWithPairedKey(MonthArry);

function showDate(day, name)
{
    document.write("<select size='1' name='" + name + "'>");
    for (i = 1; i <= 31; i++)
        document.write("<option value=" + i + ((i == day) ? " selected" : "") + ">" + ((i < 10) ? "0" : "") + i + "</option>");
    document.write("</select>");
}

function showMonth(month, name)
{
    document.write("<select size='1' name='" + name + "'>");
    for (i = 0; i < MonthArry.length; i++)
        document.write("<option value=" + (i + 1) + ((i == month) ? " selected" : "") + ">" + MonthArry[i] + "</option>");
    document.write("</select>");
}

function showYear(year, name)
{
    document.write("<select size='1' name='" + name + "'>");
    for (i = year - 10; i <= year+1; i++)
        document.write("<option value=" + i + ((i == year) ? " selected" : "") + ">" + i + "</option>");
    document.write("</select>");
}

function showHour(hour, name)
{
    document.write("<select size='1' name='" + name + "'>");
    for (i = 0; i < 24; i++)
        document.write("<option value=" + (i + 1) + ((i == hour) ? " selected" : "") + ">" + ((i < 10) ? "0" : "") + i + "</option>");
    document.write("</select>");
}

function showMinute(minute, name)
{
    document.write("<select size='1' name='" + name + "'>");
    for (i = 0; i < 60; i++)
        document.write("<option value=" + (i + 1) + ((i == minute) ? " selected" : "") + ">" + ((i < 10) ? "0" : "") + i + "</option>");
    document.write("</select>");
}

function showSecond(second, name)
{
    document.write("<select size='1' name='" + name + "'>");
    for (i = 0; i < 60; i++)
        document.write("<option value=" + (i + 1) + ((i == second) ? " selected" : "") + ">" + ((i < 10) ? "0" : "") + i + "</option>");
    document.write("</select>");
}

function isValidDate(dd, mm, yy)
{
    var dt = new Date(yy, mm - 1, dd);
    if (dd == dt.getDate() && mm - 1 == dt.getMonth() && yy == dt.getFullYear())
        return true;
    return false;
}

function isValidTime(str)
{
    var regExp = /^([0-1]?[0-9]|2[0-4]):([0-5][0-9])(:[0-5][0-9])?$/;
    var match = str.match(regExp);
    return (match == str);
}

function checkDateFormat(str) {
    var regExp;
    var match;

    var formation = false;
    var valid = false;

    // yyyy-mm-dd HH:MM:SS
    regExp = /^2\\d{3}[-/](0[1-9]|1[012]|[1-9])[-/](0[1-9]|[1-9]|[12][0-9]|3[01]) ((0|1)\\d{1}|2[0-3]|[0-9]):([0-5]\\d{1}|[0-9])(:([0-5]\\d{1})$|$)/;
    match = str.match(regExp);
    return (match == str);
}

function getFirstDayOfLastWeek(nWeek=0/*This week*/) {
    var date = new Date();
    var day = date.getDay();
    if(day == 0){
        date.setDate(date.getDate() - (nWeek*7+6));
    }
    else{
        date.setDate(date.getDate() - (nWeek*7+day-1));
    }
    return date;
}

function getFirstDayOfLastMonth(nMonth=0/*This month*/) {
	var date = new Date();
	var _y = Math.floor(nMonth/12), _m = nMonth%12;
	if (date.getMonth() == 0) {
    	_1day = new Date(date.getFullYear()-_y, 11-_m, 1);
	} else {
    	_1day = new Date(date.getFullYear()-_y, date.getMonth()-_m, 1);
	}
	return _1day;
}

function getLastDayOfLastMonth(nMonth=0/*This month*/) {
	nMonth--;
	var date = new Date();
	var _y = Math.floor(nMonth/12), _m = nMonth%12;
	if (date.getMonth() == 0) {
    	_1day = new Date(date.getFullYear()-_y, 11-_m, 1);
	} else {
    	_1day = new Date(date.getFullYear()-_y, date.getMonth()-_m, 1);
	}
	_1day.setDate(_1day.getDate()-1);
	return _1day; // yesterday of 1st day
}

var DateTimeChecker = (function() {
    // private static
    var dt = "";
    var type = "";
    var pattern = null;
    var err = "OK";

    // constructor
    var cls = function(str) {
        this.dt = str;
        this.err = "Formation error.";

        // find match pattern
        for (var p in patterns) {
            if (patterns[p][1](str, patterns[p][3])) {
                this.type = p;
                this.pattern = patterns[p][0];
                this.err = "OK";

                // Is validate
                this.validate = patterns[p][2](str, patterns[p][3]);
                if (!this.validate)
                    this.err = "DateTime is invalid.";

                break;
            }
        }

    };

    var isValid = function()
    {
        dd = arguments[0].match(/0?(\d{1,2})/)[1];
        mm = arguments[1].match(/0?(\d{1,2})/)[1];
        yy = arguments[2].match(/0?(\d{1,4})/)[1];
        var dt = new Date(yy, mm - 1, dd);
        if (dd == dt.getDate() && mm - 1 == dt.getMonth() && yy == dt.getFullYear())
            return true;

        return false;
    };

    var is_valid_a = function(str, pat) {
        var match = str.match(pat);
        return isValid(match[3], match[2], match[1]);
    };

    var is_valid_b = function(str, pat) {
        var match = str.match(pat);
        return isValid(match[1], match[2], match[3]);
    };

    var is_pat = function(str, pat) {
        var match = str.match(pat);
        //console.log(match);
        if (!match)
            return false;

        isValid(match[3], match[2], match[1]);

        return pat.test(str);
    };

    var patterns = {
        a: ['yyyy/mm/dd HH:MM:SS', function(s, p) {
                return is_pat(s, p);
            }, function(s, p) {
                return is_valid_a(s, p);
            }
            , /^(\d{4})[-/](0[1-9]|1[012]|[1-9])[-/](0[1-9]|[1-9]|[12][0-9]|3[01]) (0\d{1}|1\d{1}|2[0-3]|[0-9]):([0-5]\d{1}|[0-9]):?([0-5]\d{1}|[0-9])?$/]
        , b: ['dd/mm/yyyy HH:MM:SS', function(s, p) {
                return is_pat(s, p);
            }, function(s, p) {
                return is_valid_b(s, p);
            }
            , /^(0[1-9]|[1-9]|[12][0-9]|3[01])[-/](0[1-9]|1[012]|[1-9])[-/](\d{4}) (0\d{1}|1\d{1}|2[0-3]|[0-9]):([0-5]\d{1}|[0-9]):?([0-5]\d{1}|[0-9])?$/]
        , c: ['yyyy/mm/dd', function(s, p) {
                return is_pat(s, p);
            }, function(s, p) {
                return is_valid_a(s, p);
            }
            , /^(\d{4})[-/](0[1-9]|1[012]|[1-9])[-/](0[1-9]|[1-9]|[12][0-9]|3[01])$/]
        , d: ['dd/mm/yyyy', function(s, p) {
                return is_pat(s, p);
            }, function(s, p) {
                return is_valid_b(s, p);
            }
            , /^(0[1-9]|[1-9]|[12][0-9]|3[01])[-/](0[1-9]|1[012]|[1-9])[-/](\d{4})$/]
    };

    cls.prototype.getPattern = function() {
        return this.pattern;
    };
    cls.prototype.isValidate = function() {
        return this.validate;
    };
    cls.prototype.getError = function() {
        return this.err;
    };
    cls.prototype.getType = function() {
        return this.type;
    };

    return cls;

})();

/**
 * Function DateFormatter
 * Input: new DateFormatter('%y-%m-%d').format(new Date())
 * Return: date string
 */
var DateFormatter = (function() {
    // private static
    var formatString = "";
    var mthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    var mthFullNames = ["January", "Febuary", "March", "April", "May", "June", "July", "August", "Septempber", "October", "November", "December"];
    var dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];

    // constructor
    var cls = function(fmt) {
        this.formatString = fmt
    }

    // private static function
    var zeroPad = function(number) {
        return ("0" + number).substr(-2, 2);
    }

    var dateMarkers = {
        d: ['getDate', function(v) {
                return zeroPad(v)
            }],
        m: ['getMonth', function(v) {
                return zeroPad(v + 1)
            }],
        n: ['getMonth', function(v) {
                return mthNames[v];
            }],
        N: ['getMonth', function(v) {
                return mthFullNames[v];
            }],
        w: ['getDay', function(v) {
                return dayNames[v];
            }],
        y: ['getFullYear'],
        H: ['getHours', function(v) {
                return zeroPad(v)
            }],
        M: ['getMinutes', function(v) {
                return zeroPad(v)
            }],
        S: ['getSeconds', function(v) {
                return zeroPad(v)
            }],
        i: ['toISOString']
    };

    cls.prototype.format = function(date) {
        var dateTxt = this.formatString.replace(/%(.)/g,
                function(m, p) {
                    var rv = date[(dateMarkers[p])[0]]()
                    if (dateMarkers[p][1] != null)
                        rv = dateMarkers[p][1](rv);

                    return rv
                });

        return dateTxt;
    };

    return cls;
})();

function parseDate(str, new_format, hide_current_year=null) {
	var date = new Date(str)
    var cur_year = (new Date()).getFullYear();
    if (hide_current_year && cur_year===date.getFullYear()) // remove Y from new_format if in current year
		new_format = new_format.replace(hide_current_year, "");
	return new DateFormatter(new_format).format(date);
}

/**
 * params
 * date [JS Date()]
 * day_in_week [int] 1 (Mon) - 7 (Sun)
 */
function nextWeekdayDate(date, day_in_week, previous=false) {
  var ret = new Date(date||new Date());
  ret.setDate(ret.getDate() + (day_in_week - 1 - ret.getDay() + 7) % 7 + 1 + (previous?-7:0));
  return ret;
}

/**
 * Function monthWeek
 * Input: '2020-12-31'
 * Return: Week number of month [1..n]
 */
const monthWeek = (s) => {
  let [y, m, d] = s.split('-'); // parse date string
  let date = new Date(y, m - 1, d); // create date object
  let current_month = date.getMonth();
  let next_sunday = nextWeekdayDate(date, 7); // adjust date to next Sunday (last day of this week)
  if (current_month==next_sunday.getMonth())
    return Math.ceil(next_sunday.getDate() / 7); // return week number of the month
  else {
    prev_sunday = nextWeekdayDate(date, 7, true);
    return Math.ceil(prev_sunday.getDate() / 7) + 1; // return week number of the month
  }
}

Date.prototype.getWeekDay = function() {
  var _days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
  return _days[this.getDay()];
}
Date.prototype.getWeekDayTH = function() {
  var _days = ['อาทิตย์', 'จันทร์', 'อังคาร', 'พุธ', 'พฤหัสบดี', 'ศุกร์', 'เสาร์'];
  return _days[this.getDay()];
}
