/* Tong_Zuu */
/* ใช้แทน CscCalendar.js ไม่ได้ เพราะชื่อ function ไม่เหมือนกัน อาจจะทำให้ต้องแก้เยอะ*/

/*
	require CscBase.js
*/

		function CscTime( time ){
			this.setCscTime( time );
		}

		CscTime.prototype = jQuery.extend({} , Csc.prototype , {
			getHours : function(){
				//var h = this._getOption("hours" , "0");
				//return (parseInt( h ,10) > 9) ? h : "0"+parseInt( h ,10);
				return this._getOption("hours" , "0");
			},

			getHH : function(){
				var h = this.getHours() , hh = h.toString().length == 1 ? "0"+h : h;
				return hh;
			},

			getMinutes : function(){
				var m = this._getOption("minutes" , "00");
				return (m.toString().length == 1) ? "0"+m:m;
			},

			getSeconds : function(){
				var s = this._getOption("seconds" , "00");
				return (s.toString().length == 1) ? "0"+s:s;
			},

			getCscTime : function(format){
				return this.getHours() + this.getTimeFormat() + this.getMinutes();
			},

			getHHMM : function(){
				return this.getHH() + this.getTimeFormat() + this.getMinutes();
			},

			getTimeFormat : function( f ){
				return f || this._timeFormat || ".";
			},

			setCscTime : function( time ){
				var h , m , s;
				if(typeof time == "string" || typeof time == "number"){
					var tmp = time.toString().split( this.getTimeFormat() );
					h = tmp[0];
					m = tmp[1];
					s = tmp[2];
				}else if(typeof time == "object"){
					h = time.hours;
					m = time.minutes;
					s = time.seconds;
				}

				this.setHours( h || "0" );
				this.setMinutes( m || "00" );
				this.setSeconds( s || "00" );
			},

			setHours : function( h , notChkHour){
				var chk = notChkHour || false;
				if(chk || this._chkHours( h ) )
					this._setOption("hours" , h);
				else
					console.log("can't setHours By Value >> "+h);
			},

			setMinutes : function( m ){
				if( this._chkMinutes( m ) )
					this._setOption("minutes" , m);
				else
					console.log("can't setMinutes By Value >> "+m);
			},

			setSeconds : function( s ){
				if( this._chkSeconds( s ) )
					this._setOption("seconds" , s);
				else
					console.log("can't setSeconds By Value >> "+s);
			},

			incHours : function( n ){
				var h = parseInt(this._getOption("hours") , 10) , nh = (parseInt(n , 10) || 1);
				this.setHours(h + nh  , true);//true ไม่ต้องเช็คว่าเกิน 24 แล้วหรือเปล่า
			},

			incMinutes : function( n ){
				var m = parseInt(this._getOption("minutes") , 10) , nm = (parseInt(n , 10) || 1);
				while(60 - m <= nm){
					nm -= (60 - m);
					this.incHours();
					m = 0;
				}
				this.setMinutes(m + nm);
			},

			incSeconds : function( n ){
				var s = parseInt(this._getOption("seconds") , 10) , ns = (parseInt(n , 10) || 1);
				while(60 - s <= ns){
					ns -= (60 - s);
					this.incMinutes();
					s = 0;
				}
				this.setSeconds(s + ns);
			},

			incTime : function( n ){
				/*
					** n = 9.12000001
				*/
				if( typeof n == "number" )
					n = n.toFixed( 2 );//for n = 9.120000001 :: type number
				var tmp = n.toString().split( this.getTimeFormat() );
				if(tmp[0] && parseInt( tmp[0] , 10 ) > 0)
					this.incHours(tmp[0]);
				if(tmp[1]){
					if( tmp[1].length > 2 )
						tmp[1] = tmp[1].substr( 0 , 2 );// for tmp[1] = 12000001 :: type string
					if( parseInt( tmp[1] , 10 ) > 0)
						this.incMinutes(tmp[1]);
				}
			},

			decHours : function( n ){
				var h = parseInt(this._getOption("hours") , 10) , nh = (parseInt(n , 10) || 1);
				this.setHours(h - nh , false);
			},

			decMinutes : function( n ){
				var m = parseInt(this._getOption("minutes") , 10) , nm = (parseInt(n , 10) || 1) , num = Math.floor( nm / 60 );
				nm = nm % 60;
				if( num > 0)
					this.decDate( num );
				while(nm > m){
					nm -= m;
					this.decHours();
					m = 60;
				}
				this.setMinutes(m - nm);
			},

			decSeconds : function( n ){
				var s = parseInt(this._getOption("seconds") , 10) , ns = (parseInt(n , 10) || 1) , num = Math.floor( ns / 60 );
				ns = ns % 60;
				if( num > 0)
					this.decMinutes( num );
				while(ns > s){
					ns -= s;
					this.decMinutes();
					s = 60;
				}
				this.setSeconds(s - ns);
			},

			decTime : function( n ){
				var tmp = n.toString().split( this.getTimeFormat() );
				if(tmp[0] && parseInt( tmp[0] , 10 ) > 0)
					this.decHours(tmp[0]);

				if(tmp[1] && parseInt( tmp[1] , 10 ) > 0)
					this.decMinutes(tmp[1]);
			},

			_chkHours : function( h ){
				return (0 <= parseInt( h ,10 ) && parseInt(h ,10) < 24);
			},

			_chkMinutes : function( m ){
				return (0 <= parseInt( m ,10 ) && parseInt(m ,10) < 60);
			},

			_chkSeconds : function( s ){
				return (0 <= parseInt( s ,10 ) && parseInt(s ,10) < 60);
			}
		});


		CscCalendar = function( date ){
			/* ระวัง ถ้า CscCalendar 2 ตัว มี startYearOfTimeInMillis ไม่เท่ากัน จะเอา CscCalendar นั้นมา diff กันไม่ได้ หรือทำอะไรเกี่ยวกับ TimeInMillis ไม่ได้ ไม่เช่นนั้น value จะไม่ถูกต้อง
				ที่ set ไว้ที่ ปี 2000 เพราะไม่ให้ javascript คำนวนเวลาในจำนวนหลักที่มากเกินไป แต่ถ้าต้องการใช้งานปีที่น้อยกว่า 2000 ก็ให้เซ็ตปีใหม่ได้
			*/
			this._startYearOfTimeInMillis = (date && date.initYear) ? parseInt(date.initYear , 10) : 2000;//ปีที่เริ่มนับ TimeInMillis

			this._options = this.getInitCalendar( date );
			if(typeof date == "string")
				this.setCscCalendar( date );
		}

		CscCalendar.prototype = jQuery.extend({} , CscTime.prototype , {
			/*  -------------------------------------------------  Get Method  ------------------------------------------------- */
			_getDayOfTimeInMillis : function(){
				return 86400000;
			},

			_getHoursOfTimeInMillis : function(){
				return this._getDayOfTimeInMillis() / 24;
			},

			_getMinutesOfTimeInMillis : function(){
				return this._getHoursOfTimeInMillis() / 60;
			},

			_getSecondOfTimeInMillis : function(){
				return this._getMinutesOfTimeInMillis() / 60;
			},

			getInitCalendar : function( o ){
				var d = new Date() , obj = o || {} , result = {};
				result.year = obj.year || d.getFullYear();
				result.month = this._chkMonth( obj.month ) ? obj.month : d.getMonth()+1;
				result.date = this._chkDate( obj.date , result.month , result.year) ? obj.date : d.getDate();
				result.hours = this._chkHours( obj.hours ) ? obj.hours || "00" : d.getHours();
				result.minutes = this._chkMinutes( obj.minutes) ? obj.minutes || "00" : d.getMinutes();
				result.seconds = this._chkSeconds( obj.seconds) ? obj.seconds || "00" : d.getSeconds();
				result.engLongMonth = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
				result.thaiLongMonth = [ "มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", "ธันวาคม" ];
				return result;
			},

			getDateFormat : function(f){
				return f || this._dateFormat || "-";
			},

			getDateTimeBetweenFormat : function(f ){
				return f || this._datetimeBetweenFormat || " ";
			},

			getDDMMYYYY : function(df){
				return this.getDate() + this.getDateFormat(df) + this.getMonth() + this.getDateFormat(df) + this.getYear();
			},

			getYYYYMMDD : function(df){
				return this.getYear() + this.getDateFormat(df) + this.getMonth() + this.getDateFormat(df) + this.getDate();
			},

			getDDMMYYYYHHMM : function(){
				return this.getDDMMYYYY() + this.getDateTimeBetweenFormat() + this.getCscTime();
			},

			getDDMMYYYYHHMMSS : function(){
				return this.getDDMMYYYYHHMM() + this.getTimeFormat() + this.getSeconds();
			},

			getYYYYMMDDHHMM : function(){
				return this.getYYYYMMDD() + this.getDateTimeBetweenFormat() + this.getCscTime();
			},

			getYYYYMMDDHHMMSS : function(){
				return this.getYYYYMMDDHHMM() + this.getTimeFormat() + this.getSeconds();
			},

			getThaiFullDDMMYYYY : function(){ //1 มกราคม 2559
				return this.getDate() + " " + this._options["thaiLongMonth"][parseInt(this.getMonth())] + " " + (parseInt(this.getYear())+543);
			},

			getEngFullMMDDYYYY : function(df){ //January 1, 2016
				return this._options["engLongMonth"][parseInt(this.getMonth())] + " " + this.getDate() + ", " + this.getYear();
			},

			getDate : function(){
				var d = this._getOption("date");
				return (d.toString().length==1)?"0"+d:d;
			},

			getMonth : function(){
				var m = parseInt(this._getOption("month") ,10);
				return m.toString().length==1?"0"+m:m;
			},

			getThaiMonth : function(){
				return this._options["thaiLongMonth"][parseInt(this.getMonth())];
			},

			getEngMonth : function(){
				return this._options["engLongMonth"][parseInt(this.getMonth())];
			},

			getThaiYear : function(){
				return parseInt(this._getOption("year"))+543;
			},

			getYear : function(){
				return this._getOption("year");
			},

			getDayOfMonth : function( m , y ){
				var month = m || this.getMonth() , year = y || this.getYear();
				if(parseInt(month , 10) == 2 && parseInt(year , 10) % 4 == 0)
					return 29;
				else
					return [0,31,28,31,30,31,30,31,31,30,31,30,31][parseInt(month ,10)];
			},

			getDayInYear : function( y ){
				var d = parseInt(this.getDate() , 10)-1 , m = parseInt(this.getMonth() , 10);
				for(var i = 1;i < m; i++)
					d += this.getDayOfMonth( i , y );
				return d;
			},

			getDayOfYear : function( y ){
				return (parseInt((y || 1) , 10) % 4) ? 365 : 366;
			},

			getDayOfYear2 : function( y ){
				return (parseInt((y || this._getOption("year")) , 10) % 4 ) ? 365 : 366;
			},

			getDayUntilYear : function( year ){
				var nYear = year - this._startYearOfTimeInMillis;
				var num = Math.floor( nYear / 4 );
				var numDay = num * 1461;//1461 = 365+365+365+366
				var modYear = nYear % 4;
				return numDay + (modYear * this.getDayOfYear());
			},

			getTimeInMillis : function(){
				var d = parseInt(this.getDayUntilYear(this.getYear()) , 10) + parseInt(this.getDayInYear() , 10) , h = parseInt(this.getHours() , 10) , m = parseInt(this.getMinutes() , 10) , s = parseInt(this.getSeconds() , 10);
				return ((d * this._getDayOfTimeInMillis()) + (h * this._getHoursOfTimeInMillis()) + (m * this._getMinutesOfTimeInMillis()) + (s * this._getSecondOfTimeInMillis()));
			},

			getDiffDate : function( v ){
				var tm = v.getTimeInMillis ? v.getTimeInMillis() : parseInt( v ,10 );
				return Math.floor( Math.abs( this.getTimeInMillis() - tm) / this._getDayOfTimeInMillis() );
			},

			getDiffTime : function( v ){
				var tm = v.getTimeInMillis ? v.getTimeInMillis() : parseInt( v ,10 );
				var d = Math.abs( this.getTimeInMillis() - tm) / this._getMinutesOfTimeInMillis() ;
				var m = ( d % 60 );
				m = m.toString().length == "1" ? "0"+m : m;
				return Math.floor( d / 60 ) + this.getTimeFormat() + m;
			},

			/* -------------------------------------------------  Set Method  ------------------------------------------------- */
			setDateTimeBetweenFormat : function(f ){
				if(typeof f != "string")
					return;
				this._datetimeBetweenFormat = f;
			},

			setCscCalendar : function( calendar ){
				if(typeof calendar == "string"){
					var tmp = calendar.toString().split( this.getDateTimeBetweenFormat() );
					this.setCscDate( tmp[0] );
					this.setCscTime( tmp[1] );
				}else if(typeof calendar == "object"){+
					this.setCscDate( calendar );
					this.setCscTime( calendar );
				}
			},

			setCscDate : function( date ){
				var d,m,y,obj;
				if(typeof date == "undefined"){
					return false;
				}else if(typeof date == "string"){
					var tmp = date.toString().split( this.getDateFormat() );
					if(tmp.length == 3){
						if(tmp[0].length == 4){
							y = tmp[0];
							d = tmp[2];
						}else{
							y = tmp[2];
							d = tmp[0];
						}
						m = tmp[1];
					}
				}else if(typeof date == "object"){
					d = date.date;
					m = date.month;
					y = date.year;
				}

				if(y)this.setYear( y );
				if(m)this.setMonth( m );
				if(d)this.setDate( d );
			},

			setDate : function( d ){
				if( this._chkDate( d ) )
					this._setOption("date" , d);
				else
					console.log("can't setDate By Value >> "+d);
			},

			setMonth : function( m ){
				if( this._chkMonth( m ) )
					this._setOption("month" , m);
				else
					console.log("can't setMonth By Value >> "+m);
			},

			setYear : function( y ){
				this._setOption("year" , y);
				if(parseInt(y ,10) < this._startYearOfTimeInMillis)
					this._startYearOfTimeInMillis = parseInt(y ,10);
			},

			setTimeInMillis : function( millis ){
				var Vmillis = (millis.getTimeInMillis) ? millis.getTimeInMillis() : millis;
				/* manage date */
				var d = Math.floor( Vmillis / this._getDayOfTimeInMillis() );

				this.setYear(this._startYearOfTimeInMillis);
				this.setMonth("01");
				this.setDate("01");
				this.setHours("00");
				this.setMinutes("00");
				this.setSeconds("00");

				/* 1461 = 365+365+365+366 */
				while(d >= 1461){
					d -= 1461;
					this.incYear(4);
				}
				var dy;
				while((dy = parseInt(this.getDayOfYear() , 10)) <= d){
					d -= dy;
					this.incYear();
				}

				var dm;
				while((dm = parseInt( this.getDayOfMonth() , 10)) <= d){
					d -= dm;
					this.incMonth();
				}

				if(d > 0)
					this.incDate(d);
				/* end manage date */

				/* manage time */
				var t = Vmillis % this._getDayOfTimeInMillis();

				var n = Math.floor( t / this._getHoursOfTimeInMillis() );
				if(n <= 0)return;
				this.incHours( n );

				t =  t % this._getHoursOfTimeInMillis();

				n = Math.floor( t / this._getMinutesOfTimeInMillis() );
				if(n <= 0)return;
				this.incMinutes( n );

				t =  t % this._getMinutesOfTimeInMillis();

				n = Math.floor( t / this._getSecondOfTimeInMillis() );
				if(n <= 0)return;
				this.incSeconds( n );

				/* end manage time */
			},

			/* -------------------------------------------------  Increase And Decrease Method  ------------------------------------------------- */
			incDate : function( n ){
				var d = parseInt(this._getOption("date") , 10) , nd = (parseInt(n , 10) || 1) , nm = parseInt(this.getDayOfMonth() ,10);
				while(nm - d < nd){
					nd -= (nm - d);
					this.incMonth();
					nm = parseInt(this.getDayOfMonth() ,10);
					d = 0;
				}
				this.setDate(d + nd);
			},

			incDateR : function( n ){
				var d = parseInt(this._getOption("date") , 10) , nd = (parseInt(n , 10) || 1) , nm = parseInt(this.getDayOfMonth() ,10);
				while(nm - d < nd){
					nd -= (nm - d);
					this.incMonth();
					nm = parseInt(this.getDayOfMonth() ,10);
					d = 0;
				}
				this.setDate(d + nd);
				return this;
			},

			incMonth : function( n ){
				var m = parseInt(this._getOption("month") , 10) , nm = (parseInt(n , 10) || 1);
				while(12 - m < nm){
					nm -= (12 - m);
					this.incYear();
					m = 0;
				}
				this.setMonth(m + nm);
			},

			incYear : function( n ){
				this.setYear( parseInt(this._getOption("year") , 10) + (parseInt(n , 10) || 1));
			},

			incHours : function( n ){
				var h = parseInt(this._getOption("hours") , 10) , nh = (parseInt(n , 10) || 1);
				while(24 - h <= nh){
					nh -= (24 - h);
					this.incDate();
					h = 0;
				}
				this.setHours(h + nh);
			},

			decDate : function( n ){
				var d = parseInt(this._getOption("date") , 10) , nd = (parseInt(n , 10) || 1);
				while(nd >= d){
					nd -= d;
					this.decMonth();
					d = parseInt(this.getDayOfMonth() ,10);;
				}
				this.setDate(d - nd);
			},

			decDateR : function( n ){
				var d = parseInt(this._getOption("date") , 10) , nd = (parseInt(n , 10) || 1);
				while(nd >= d){
					nd -= d;
					this.decMonth();
					d = parseInt(this.getDayOfMonth() ,10);;
				}
				this.setDate(d - nd);
				return this;
			},

			decMonth : function( n ){
				var m = parseInt(this._getOption("month") , 10) , nm = (parseInt(n , 10) || 1);
				while(nm >= m){
					nm -= m;
					this.decYear();
					m = 12;
				}
				this.setMonth(m - nm);
			},

			decYear : function( n ){
				this.setYear( parseInt(this._getOption("year") , 10) - (parseInt(n , 10) || 1));
			},

			decHours : function( n ){
				var h = parseInt(this._getOption("hours") , 10) , nh = (parseInt(n , 10) || 1);
				var num = Math.floor( nh / 24 );
				nh = nh % 24;
				if( num > 0)
					this.decDate( num );
				while(nh > h){
					nh -= h;
					this.decDate();
					h = 24;
				}
				this.setHours(h - nh);
			},

			/* -------------------------------------------------  Check Method  ------------------------------------------------- */

			_chkDate : function( d , m , y){
				return (0 < parseInt( d ,10 ) && parseInt( d ,10 ) <= this.getDayOfMonth( m , y ));
			},

			_chkMonth : function( m ){
				return (0 < parseInt( m ,10 ) && parseInt(m ,10) <= 12);
			},

			equals : function( t ){
				return this.getTimeInMillis() == ((t.getTimeInMillis) ? t.getTimeInMillis() : t);
			},

			equalsDate : function( t ){
				return this.getDDMMYYYY() == ((t.getDDMMYYYY) ? t.getDDMMYYYY() : t);
			},

			beforeDate : function( t ){
				return this.getYYYYMMDD() < ((t.getYYYYMMDD) ? t.getYYYYMMDD() : t);
			},

			beforeEqualsDate : function( t ){
				return (this.beforeDate( t ) || this.equalsDate( t ));
			},

			afterDate : function( t ){
				return this.getYYYYMMDD() > ((t.getYYYYMMDD) ? t.getYYYYMMDD() : t);
			},

			afterEqualsDate : function( t ){
				return (this.afterDate( t ) || this.equalsDate( t ));
			},

			equalsDateTime : function( t ){
				return this.getTimeInMillis() == ((t.getTimeInMillis) ? t.getTimeInMillis() : t);
			},

			beforeDateTime : function( t ){
				return this.getTimeInMillis() < ((t.getTimeInMillis) ? t.getTimeInMillis() : t);
			},

			beforeEqualsDateTime : function( t ){
				return (this.beforeDateTime( t ) || this.equalsDateTime( t ));
			},

			afterDateTime : function( t ){
				return this.getTimeInMillis() > ((t.getTimeInMillis) ? t.getTimeInMillis() : t);
			},

			afterEqualsDateTime : function( t ){
				return (this.afterDateTime( t ) || this.equalsDateTime( t ));
			}
		});