/**
 *  Yahho Calendar - Japanized Popup Calendar
 *  @see       http://0-oo.net/sbox/javascript/yahho-calendar
 *  @version   0.2.2 beta 1
 *  @copyright 2008 dgbadmin@gmail.com
 *  @license   http://0-oo.net/pryn/MIT_license.txt (The MIT license)
 */

var YahhoCal = {
    //YUIカレンダー日本語化設定
    YUI_CAL_CONFIG_JP: {
          close: true
        , my_label_year_position: 1
        , my_label_year_suffix: "年 "
        , my_label_month_suffix: "月"
        , months_long: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]
        , weekdays_short: ["日", "月", "火", "水", "木", "金", "土"]
        , hide_blank_weeks: true
    },

    //loadYUI()で読み込むYUIのサーバ（@see http://developer.yahoo.com/yui/articles/hosting/ ）
    YUI_SERVER: "http://yui.yahooapis.com/",

    //loadYUI()で読み込むYUIのバージョン
    YUI_VERSION: "2.5.1",
    
    //入力要素をラップするアダプタ
    adapters: {}
};
/**
 *    カレンダーを表示する
 *    @param    String    inputId    入力要素のid or 年の入力要素のid
 *    @param    String    monthId    (optional) 月の入力要素のid
 *    @param    String    dateId     (optional) 日の入力要素のid
 *    @return   Boolean   カレンダーの表示ができたかどうか
 */
YahhoCal.render = function(inputId, monthId, dateId) {
    if (!window.YAHOO || !YAHOO.widget.Calendar) {    //YUIを読み込んでいない場合
        return false;
    }
    
    var currentId = (this.currentId = dateId || inputId); //入力要素を特定するID

    //アダプタを取得
    if (!this.adapters[currentId]) {
        this.adapters[currentId] = this.createAdapter(inputId, monthId, dateId);
    }
    var adapter = this.adapters[currentId];

    var cal = this.cal;
    if (cal) {    //再表示の場合
        YAHOO.util.Dom.insertAfter(this.place, currentId);
        cal.show();
    } else {    //初めて表示する場合
        cal = this.cal = this.createCalendar(currentId);
    }

    //入力済みの日付を取得
    var val = adapter.getDate();
    var y = val[0], m = val[1], d = val[2];
    var shown = new Date(y, m - 1, d);

    //表示設定
    var pagedate = "", selected = "";
    if ((shown.getFullYear() == y && shown.getMonth() + 1 == m && shown.getDate() == d)) {
        //日付として正しい場合
        pagedate = m + "/" + y;
        selected = m + "/" + d + "/" + y;
    } else {
        shown = new Date();
    }
    cal.cfg.setProperty("pagedate", pagedate);    //表示する年月
    cal.cfg.setProperty("selected", selected);    //選択状態の日付

    cal.render();

    this.showHolidays(shown);
    
    return true;
};
/**
 *    入力要素とカレンダーとのポリモフィズムなアダプタを生成する
 */
YahhoCal.createAdapter = function(inputId, monthId, dateId) {
    var adapter = {};

    if (!monthId) {    //テキストボックス1つの場合
        var ymd = document.getElementById(inputId);
        adapter.getDate = function() { return ymd.value.split("/"); };
        adapter.setDate = function(y, m, d) { ymd.value = y + "/" + m + "/" + d; };
        return adapter;
    }
    
    //年・月・日が分かれている場合
    var ey = document.getElementById(inputId);
    var em = document.getElementById(monthId);
    var ed = document.getElementById(dateId);
 
    if (ey.tagName == "INPUT") {    //テキストボックスの場合
        adapter.getDate = function() { return [ey.value, em.value, ed.value]; };
        adapter.setDate = function(y, m, d) { ey.value = y; em.value = m; ed.value = d; };
        return adapter;
    }
    
    //選択リストの場合
    var getValue = function(sel) { return sel.options[sel.selectedIndex].text; };
    var setValue = function(sel, value) {
        for (var i = 0; i < sel.length; i++) {
            if (sel.options[i].text == value) {
                sel.options[i].selected = true;
                return;
            }
        }
    };
    adapter.getDate = function() { return [getValue(ey), getValue(em), getValue(ed)]; };
    adapter.setDate = function(y, m, d) { setValue(ey, y); setValue(em, m); setValue(ed, d); };
    return adapter;
};
/**
 *    カレンダーを生成する
 */
YahhoCal.createCalendar = function(insertId) {
    //YUI skinを適用
    YAHOO.util.Dom.addClass(document.getElementsByTagName("body")[0], "yui-skin-sam");

    //カレンダーの場所を作る
    var place = (this.place = document.createElement("div"));
    YAHOO.util.Dom.setStyle(place, "position", "absolute");
    YAHOO.util.Dom.insertAfter(place, insertId);

    //カレンダー生成
    var cal = new YAHOO.widget.Calendar(place, this.YUI_CAL_CONFIG_JP);

    //日付を選択された時のイベント
    cal.selectEvent.subscribe(function(eventName, date) {
        var dateStr = date[0][0];
        YahhoCal.adapters[YahhoCal.currentId].setDate(dateStr[0], dateStr[1], dateStr[2]);
        cal.hide();
    }, cal, true);

    //月を移動された時のイベント
    cal.changePageEvent.subscribe(function() {
        YahhoCal.showHolidays(cal.cfg.getProperty("pagedate"));
    }, cal, true);
    
    return cal;
};
/**
 *    祝日を表示する
 */
YahhoCal.showHolidays = function(target) {
    if (!window.GCalHolidays) {    //GCalHolidays.jsを読み込んでいない場合
        return;
    }
    GCalHolidays.get(this.setHolidays, target.getFullYear(), target.getMonth() + 1);
};
/**
 *    祝日表示を設定する
 */
YahhoCal.setHolidays = function(holidays) {
    if (holidays.length === 0) {
        return;
    }
    
    //該当年月のままか確認
    var first = holidays[0];
    var table = YAHOO.util.Dom.getElementsByClassName("y" + first.year, "table", this.place)[0];
    var tbody = YAHOO.util.Dom.getElementsByClassName("m" + first.month, "tbody", table)[0];
    if (!table || !tbody) {
        return;
    }

    //祝日設定
    for (var i in holidays) {
        var h = holidays[i];
        var td = YAHOO.util.Dom.getElementsByClassName("d" + h.date, "td", tbody)[0];
        YAHOO.util.Dom.addClass(td, "holiday");
        td.title = h.title;    //マウスオーバーで祝日名を表示
    }
};
/**
 *    必要なYUIのJavaScriptとCSSを読み込む
 */
YahhoCal.loadYUI = function() {
    var url = this.YUI_SERVER + this.YUI_VERSION;
    var head = document.getElementsByTagName("head")[0];

    var css = document.createElement("link");
    css.rel = "stylesheet";
    css.type = "text/css";
    css.href = url + "/build/calendar/assets/skins/sam/calendar.css";
    head.appendChild(css);

    var addScript = function(path) {
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.src = url + path;
        head.appendChild(script);
    };
    
    addScript("/build/yahoo-dom-event/yahoo-dom-event.js");
    
    //yahoo-dom-event.jsがloadされるまで待つ
    var limit = 3000, interval = 300, time = 0;
    var loadedId = setInterval(function(){
        if (window.YAHOO) {
            clearInterval(loadedId);
            addScript("/build/calendar/calendar-min.js");
        } else if ((time += interval) > limit) {    //タイムアウト
            clearInterval(loadedId);
        }
    }, interval);
};
/**
 *    週の初めを月曜日にする
 */
YahhoCal.setMondayAs1st = function() {
    this.YUI_CAL_CONFIG_JP.start_weekday = 1;
};
