/**
 * jQuery.calendar
 *
 * @version    1.0.3
 * @author     Hiroshi Hoaki <rewish.org@gmail.com>
 * @copyright  2010 Hiroshi Hoaki
 * @license    http://rewish.org/license/mit The MIT License
 * @link       http://rewish.org/javascript/jquery_calendar
 */
(function (b) {
	b.fn.calendar = function (e) {
		return this.each(function () {
			(new d).init(b(this), e).build().show()
		})
	};
	var a = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
	var c = new Date;

	function d() {}
	d.prototype = {
		init: function (f, e) {
			this.setOption(e);
			this.elem = b("<div/>").addClass(this.option.cssClass).css("z-index", 2);
			this.wrap = b("<div/>").append(this.elem).css({
				position: "relative",
				overflow: "hidden"
			});
			f.append(this.wrap);
			this.view = {};
			this.preloadEvents = {};
			return this.buildNavi().buildTable().buildCaption().buildTodayLink()
		},
		setOption: function (e) {
			if (this.option && !e) {
				return this
			}
			if (this.option) {
				b.extend(this.option, e);
				return this
			}
			this.option = b.extend({
				lang: "ja",
				year: c.getFullYear(),
				month: c.getMonth() + 1,
				week: {
					en: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
					ja: ["\u65e5", "\u6708", "\u706b", "\u6c34", "\u6728", "\u91d1", "\u571f"]
				},
				caption: {
					en: "%Y-%M",
					ja: "%Y\u5e74%M\u6708"
				},
				navi: {
					en: ["Prev", "Next"],
					ja: ["<<", ">>"]
				},
				todayLink: {
					en: "Today [%Y-%M-%D]",
					ja: "\u4eca\u65e5 [%Y\u5e74%M\u6708%D\u65e5]"
				},
				moveTime: 700,

				Past: 100,
				Now: 200,
				
				fullMonth:null,
				fullYear:null,

				moveTime: 700,
				events: {},
				hideOther: false,
				cssClass: "jqueryCalendar",
				addDay: function () {},
				addEvent: function (h, f) {
					var g = typeof f.url !== "undefined" ? b("<a/>").attr("href", f.url) : b("<span/>");
					if (f.id) {
						g.attr("id", "event-" + f.id)
					}
					if (f.title) {
						g.attr("title", f.title)
					}
					g.text(h.text());
					h.text("").append(g).addClass("event")
				},
				beforeMove: function () {},
				afterMove: function () {},
				preloadEvent: function () {}
			}, e);
			return this
		},
		buildNavi: function () {
			if (!this.option.navi) {
				return this
			}
			var e = this;
			var f = function (i, k, l) {
					var h = new Date(e.option.year, (e.option.month + k) - 1, 1);
					var j = b("<a/>").text(l).attr("href", "javascript:void(0)").click(function () {
						e.move(k);
						return false
					});
					return b("<li/>").addClass(i).append(j)
				};
			var g = typeof this.option.navi === "object" ? this.option.navi[this.option.lang] : this.option.navi;
			this.elem.append(b("<ul/>").addClass("navi").append(f("prev", -1, g[0]), f("next", 1, g[1])));
			return this
		},
		buildTable: function () {
			this.tr = b("<tr/>");
			this.td = b("<td/>");
			this.table = b("<table/>");
			var h = [];
			var f = this.option.week[this.option.lang] || this.option.week;
			for (var g = 0, e; e = f[g]; g++) {
				h[h.length] = '<th class="' + a[g] + '">' + e + "</td>"
			}
			this.thead = b("<thead/>").append(this.tr.clone().html(h.join("")));
			this.tbody = b("<tbody/>");
			this.elem.append(b("<div/>").addClass("main").append(this.table.addClass("calendar").append(this.thead).append(this.tbody)));
			return this
		},
		buildCaption: function () {
			if (this.option.caption && !this.caption) {
				this.caption = b('<div class="caption"><a href="#"></a></div>');
				this.table.before(this.caption)
			}
			return this
		},
		buildTodayLink: function () {
			var f = this.getKey(c).split("-");
			var g = typeof this.option.todayLink === "object" ? this.option.todayLink[this.option.lang] : this.option.todayLink;
			var e = this;
			this.table.after(b("<div/>").addClass("todayLink").append(b("<a/>").text(g.replace(/%Y/i, f[0]).replace(/%M/i, f[1]).replace(/%D/i, f[2])).attr("href", "javascript:void(0)").click(function () {
				e.option.year = c.getFullYear();
				e.option.month = c.getMonth() + 1;
				e.rebuild().show().resetWrap()
			})));
			return this
		},
		build: function () {
			this.prevFill();
			this.current = new Date(this.option.year, this.option.month - 1, 1);
			var f = new Date(this.option.year, this.option.month, 0).getDate();
			for (var e = 1; e <= f; e++) {
				this.current.setDate(e);
				this.option.day = e;
				this.option.addDay(this.addDay(this.current, "currentMonth"))
			}
			this.option.day = null;
			this.nextFill();
			this.addEvent();
			return this
		},
		rebuild: function () {
			this.tbody.empty();
			this.view = {};
			return this.build()
		},
		prevFill: function () {
			var g = new Date(this.option.year, this.option.month - 1, 0),
				f = g.getDate(),
				e = f - g.getDay();
			if (f - e >= 6) {
				return this
			}
			for (; e <= f; e++) {
				g.setDate(e);
				this.addDay(g, "otherMonth", this.option.hideOther)
			}
			return this
		},
		nextFill: function () {
			var f = new Date(this.option.year, this.option.month, 1),
				g = 7 - f.getDay();
			if (g >= 7) {
				return this
			}
			for (var e = 1; e <= g; e++) {
				f.setDate(e);
				this.addDay(f, "otherMonth", this.option.hideOther)
			}
			return this
		},
		addDay: function (e, h, g) {
			var f = h === "otherMonth" ? h + this.getKey(e) : this.getKey(e);
			this.view[f] = this.td.clone().addClass(h).addClass(a[e.getDay()]);
			this.view[f].text(g ? " " : e.getDate());
			if (f !== "otherMonth") {
				this.view[f].attr("id", ["calendar", this.getKey(e)].join("-"))
			}
			return this.view[f]
		},
		getKey: function (e, g) {
			if (typeof e === "string") {
				e = e.split("-")
			}
			var f = [e[0] || e.getFullYear(), ("0" + (e[1] || e.getMonth() + 1)).slice(-2), ("0" + (e[2] || e.getDate())).slice(-2)];
			if (g === true) {
				return f
			}
			return f.join("-")
		},
		addEvent: function () {
			var e = this;
			b.each(e.option.events, function (f, g) {
				var i = e.view[e.getKey(f)];
				try {
					e.option.addEvent(i, g)
				} catch (h) {}
			});
			return this
		},
		show: function () {
			var g = this.getKey(c),
				j, i = 0,
				f = this;
			b.each(f.view, function (e) {
				if (i % 7 === 0 || i === 0) {
					j = i % 2 === 0 ? f.tr.clone().addClass("even") : f.tr.clone().addClass("odd");
					f.tbody.append(j)
				}
				if (e === g && !e.match("otherMonth")) {
					this.addClass("today")
				}
				j.append(this);
				i++
			});
			this.setCaption();
			try {
				var h = this.getKey(this.current).split("-");
				this.preloadEvents = this.option.preloadEvent(h[0], h[1])
			} catch (k) {}
			return this
		},
			setCaption: function () {
				if (!this.option.caption) {
					return this
				}
				var hn = location.hostname;
				if(this.option.fullMonth === null && this.option.fullYear === null){
					this.caption.children().attr('href','http://' + hn + '/archive/' + this.option.year + '/' + this.option.month + '/');
				}else{
				this.caption.children().attr('href','http://' + hn + '/archive/' + this.option.fullYear + '/' + this.option.fullMonth + '/');
				}
				this.caption.children().text(this.getCaption(this.current));
				return this
			},
		getCaption: function (f) {
			f = this.getKey(f).split("-");
			var e = typeof this.option.caption === "object" ? this.option.caption[this.option.lang] : this.option.caption;
			return e.replace(/%Y/i, f[0]).replace(/%M/i, f[1])
		},
		move: function (h) {
			var g = this.elem.innerWidth();
			var k = this.elem.position();
			var j = this.elem.clone().css({
				position: "absolute",
				top: k.top + "px",
				left: k.left + "px",
				zIndex: 1
			});
			this.resetWrap();
			this.wrap.append(j);
			this.option.month = this.option.month + h;
			var f = new Date(this.option.year, this.option.month - 1, 1);

			this.option.fullMonth = f.getMonth()+1;
			this.option.fullYear = f.getFullYear();
			
			f = this.getKey(f, true);

			this.option.beforeMove(this.option, f[0], f[1]);
			this.setPreloadEvent(h);
			this.rebuild().show();
			var i = this.option.moveTime;
			this.wrap.animate({
				height: this.elem.innerHeight()
			}, i);
			if ((h + "").charAt(0) !== "-") {
				j.animate({
					marginLeft: "-" + g + "px"
				}, i, function () {
					j.remove()
				})
			} else {
				this.elem.css({
					position: "absolute",
					marginLeft: "-" + g + "px"
				});
				var e = this;
				this.elem.animate({
					marginLeft: 0
				}, i, function () {
					j.remove();
					e.elem.css("position", "static")
				})
			}
			this.option.afterMove(this.option, f[0], f[1])
		},
		resetWrap: function () {
			this.wrap.css({
				width: this.elem.innerWidth() + "px",
				height: this.elem.innerHeight() + "px"
			});
			return this
		},
		setPreloadEvent: function (g) {
			var f = g === 1 ? "next" : "prev";
			try {
				if (typeof this.preloadEvents[f] === "object") {
					return this.option.events = this.preloadEvents[f]
				}
				if (typeof this.preloadEvents === "object") {
					return this.option.events = this.preloadEvents
				}
			} catch (h) {}
		}
	}
})(jQuery);
