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

    function d() {}
    d.prototype = {
        init: function (f, e) {
            this.setOption(e);
            this.elem = c("<div />").addClass(this.option.cssClass).css("z-index", 2);
            this.wrap = c("<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) {
                c.extend(this.option, e);
                return this
            }
            this.option = c.extend({
                lang: "ja",
                year: a.getFullYear(),
                month: a.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: ["\u524d\u306e\u6708", "\u6b21\u306e\u6708"]
                },
                todayLink: {
                    en: "Today [%Y-%M-%D]",
                    ja: "\u4eca\u65e5 [%Y\u5e74%M\u6708%D\u65e5]"
                },
                moveTime: 700,
                events: {},
                hideOther: false,
                cssClass: "jqueryCalendar",
                addDay: function () {},
                addEvent: function (h, f) {
                    var g = typeof f.url != "undefined" ? c("<a />").attr("onClick", f.url) : c("<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 = c("<a />").text(l).attr("href", "javascript:void(0)").click(function () {
                    e.move(k);
                    return false
                });
                return c("<li />").addClass(i).append(j)
            };
            var g = typeof this.option.navi === "object" ? this.option.navi[this.option.lang] : this.option.navi;
            this.elem.append(c("<ul />").addClass("navi").append(f("prev", -1, g[0])).append(f("next", 1, g[1])));
            return this
        },
        buildTable: function () {
            this.tr = c("<tr />");
            this.td = c("<td />");
            this.table = c("<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="', b[g], '">', e, "</td>"].join("")
            }
            this.thead = c("<thead />").append(this.tr.clone().html(h.join("")));
            this.tbody = c("<tbody />");
            this.elem.append(c("<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 = c("<div />").addClass("caption");
                this.table.before(this.caption)
            }
            return this
        },
        buildTodayLink: function () {
            var f = this.getKey(a).split("-");
            var g = typeof this.option.todayLink === "object" ? this.option.todayLink[this.option.lang] : this.option.todayLink;
            var e = this;
            this.table.after(c("<div />").addClass("todayLink").append(c("<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 = a.getFullYear();
                e.option.month = a.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.addDay(this.addDay(this.current, "currentMonth"))
            }
            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(b[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;
            c.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(a),
                j, i = 0,
                f = this;
            c.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
            }
            this.caption.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);
            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);
