/*
 *  Title: Timer.js
 *   Date: 2008/06/11
 * Author: Poturi
 *
 * Timer.js
 * Copyright (c) 2008 Poturi, All Rights Reserved.
 * http://www.poturi.net/
 *
 * ソースコードの改変・再頒布は自由ですが、
 * その際はこのCopyrightを明記してください。
 * 商用利用は不可です。
 */

function Timer(ig_prefs, cookie, sound) {
    this.ig_prefs = ig_prefs;
    this.cookie = cookie;
    this.finish_time = this.get_finish_time();
    this.message = this.get_message();
    this.sound = sound;

    this.remain = 0;    // 残り時間（ミリ秒）
    this.ten_min = 0;   // 10分の位の値
    this.min = 0;       // 1分の位の値
    this.ten_sec = 0;   // 10秒の位の値
    this.sec = 0;       // 1秒の位の値
    this.mmss = this.get_mmss(this.remain);    // MMSS形式の時間（例: 12'34）

    this.timer_interval_id = false;   // setInterval()のID
    this.sound_interval_id = false;   // setInterval()のID

    this.init_timer();
}

// ig_prefsまたはCookieから終了時間を取得
Timer.prototype.get_finish_time = function() {
    if (this.ig_prefs) {
        if (this.ig_prefs.getInt("finish_time")) {
            return this.ig_prefs.getInt("finish_time");
        }
        else { return 0; }
    }
    else {
        this.cookie.load();
        if (this.cookie.finishtime) { return parseInt(this.cookie.finishtime); }
        else { return 0; }
    }
}

// ig_prefsから表示メッセージを取得
Timer.prototype.get_message = function() {
    if (this.ig_prefs) {
        return this.ig_prefs.getString("message");
    }
    else { return "Timer: Ting-a-ling!" }
}

// タイマーを初期化
Timer.prototype.init_timer = function() {
    this.set_button();
    if (!this.finish_time) { this.set_display(this.mmss); }
    else { this.restore_timer(this.finish_time); }
}

// finish_timeからタイマーを復元する
Timer.prototype.restore_timer = function(finish) {
    // 残り時刻 = 終了時刻 - 現在時刻
    var my_date = new Date();
    var now = my_date.getTime();
    this.remain = finish - now;
    if (this.remain > 0) {
        this.mmss = this.get_mmss(this.remain);
        this.set_display(this.mmss);
        this.start_timer();
    }
    else {
        this.clear();
    }
}

// ユーザインタフェースのMおよびSボタンを押すときに呼び出す
// 10分、1分、1秒の位は0～9、10秒の位は0～5でループさせる
Timer.prototype.set_time = function(arg) {
    if (this.timer_interval_id) { return false; }
    switch (arg) {
        case "ten_min":
            if ((this.ten_min + 1) % 10) { this.ten_min ++; }
            else { this.ten_min = 0; }
            break;
        case "min":
            if ((this.min + 1) % 10) { this.min ++; }
            else { this.min = 0; }
            break;
        case "ten_sec":
            if ((this.ten_sec + 1) % 6) { this.ten_sec ++; }
            else { this.ten_sec = 0; }
            break;
        case "sec":
            if ((this.sec + 1) % 10) { this.sec ++; }
            else { this.sec = 0; }
            break;
        default:
            break;
    }
    this.remain = this.get_remain(this.ten_min, this.min, this.ten_sec, this.sec);
    this.mmss = this.get_mmss(this.remain);
    this.set_display(this.mmss);
}

// ten_min、min、ten_s、sプロパティからミリ秒を生成
Timer.prototype.get_remain = function(ten_min, min, ten_sec, sec) {
    return parseInt(ten_min) * 600000 + parseInt(min) * 60000 + parseInt(ten_sec) * 10000 + parseInt(sec) * 1000;
}

// ミリ秒からMMSS形式の文字列を生成
Timer.prototype.get_mmss = function(milli_sec) {
    this.ten_min = Math.floor(milli_sec / 600000);
    milli_sec %= 600000;
    this.min = Math.floor(milli_sec / 60000);
    milli_sec %= 60000;
    this.ten_sec = Math.floor(milli_sec / 10000);
    milli_sec %= 10000;
    this.sec = Math.floor(milli_sec / 1000);
    return "" + this.ten_min + this.min + "\'" + this.ten_sec + this.sec;
}

// カウントダウンを開始して、スタートボタンをストップボタンに変更
Timer.prototype.start_timer = function() {
    // setInterval()が稼動していない場合はスタートボタンとして動作
    if (!this.timer_interval_id) {
        this.toggle_button("stop");
        // 0.999秒加えることで、1秒後にカウントダウンが始まり、
        // 0秒になると同時に終了する
        this.remain += 999;
        if (!this.finish_time) {
            // 終了時刻　= 現在時刻 + 残り時間
            var my_date = new Date();
            var now = my_date.getTime();
            this.finish_time = now + this.remain;
            this.set_finish_time(this.finish_time);
        }
        var self = this;
        this.timer_interval_id = setInterval(
            function() { self.countdown(); }, 100
        );
    }
    // setInterval()が稼動している場合はStopボタンとして動作
    else {
        this.toggle_button("start");
        this.stop_timer();
    }
}

// Cookieまたはig_prefsに残り時間を設定する
Timer.prototype.set_finish_time = function(finish) {
    if (this.ig_prefs) {
        this.ig_prefs.set("finish_time", finish);
    }
    else {
        this.cookie.finishtime = finish;
        this.cookie.store();
    }
}

// 残り時間をカウントダウンして0秒になると音を鳴らす
Timer.prototype.countdown = function() {
    // remainに0.999秒加えたので、1秒前に終了させる
    if (this.remain > 1000) {
        var my_date = new Date();
        var now = my_date.getTime();
        this.remain = this.finish_time - now;
        this.mmss = this.get_mmss(this.remain);
        this.set_display(this.mmss);
    }
    else {
        this.remain = 0;
        this.mmss = this.get_mmss(this.remain);
        this.set_display(this.mmss);
        this.finish_time = 0;
        this.set_finish_time(this.finish_time);
        clearInterval(this.timer_interval_id);
        this.play_sound();
        // Safariで音声とポップアップをずらすためのディレイ
        var self = this;
        var delay = setTimeout( function() { self.show_confirm(); }, 200);
    }
}

// 残り時間を保持したままタイマーを止める
Timer.prototype.stop_timer = function() {
    clearInterval(this.timer_interval_id);
    this.timer_interval_id = false;
    if (this.sound_interval_id) {
        clearInterval(this.sound_interval_id);
        this.sound_interval_id = false;
        this.sound.stop();
    }
    this.finish_time = 0;
    this.set_finish_time(this.finish_time);
    this.remain = Math.floor(this.remain / 1000) * 1000;
    this.get_mmss(this.remain);
}

// 音を再生
Timer.prototype.play_sound = function() {
    var self = this;
    this.sound.loadSound("/gadgets/timer/sound/alarm.mp3", true);
    this.sound_interval_id = setInterval(
        function() { self.sound.start(); }, 1500
    );
}

// ポップアップを表示
Timer.prototype.show_confirm = function() {
    var my_confirm = confirm(this.message);
    if (my_confirm) { this.clear(); }
}

// 数値表示を更新する
Timer.prototype.set_display = function(str) {
    var text = document.createTextNode(str);
    var display = document.getElementById("display");
    if (display.hasChildNodes()) {
        display.replaceChild(text, display.firstChild);
    }
    else {
        display.appendChild(text);
    }
}

// スタートボタンとストップボタンを入れ替える
Timer.prototype.toggle_button = function(arg) {
    var start_button = document.getElementById("start_button");
    switch (arg) {
        case "start":
            start_button.style.backgroundImage = "url('/gadgets/timer/img/button/start.png')";
            break;
        case "stop":
            start_button.style.backgroundImage = "url('/gadgets/timer/img/button/stop.png')";
            break;
        default:
            break;
    }
}

// 全プロパティを初期化する
Timer.prototype.clear = function() {
    this.remain = 0;
    this.ten_min = 0;
    this.min = 0;
    this.ten_sec = 0;
    this.sec = 0;
    this.mmss = this.get_mmss(this.remain);
    this.finish_time = 0;
    this.set_finish_time(this.finish_time);
    if (this.timer_interval_id) {
        clearInterval(this.timer_interval_id);
        this.timer_interval_id = false;
    }
    if (this.sound_interval_id) {
        clearInterval(this.sound_interval_id);
        this.sound_interval_id = false;
        this.sound.stop();
    }
    this.toggle_button("start");
    this.set_display(this.mmss);
}

// ボタンのonclick属性を設定する
Timer.prototype.set_button = function() {
    var self = this;
    document.getElementById("start_button").onclick = function() {
        self.start_timer(); return false;
    };
    document.getElementById("ten_min_button").onclick = function() {
        self.set_time("ten_min"); return false;
    };
    document.getElementById("min_button").onclick = function() {
        self.set_time("min"); return false;
    };
    document.getElementById("ten_sec_button").onclick = function() {
        self.set_time("ten_sec"); return false;
    };
    document.getElementById("sec_button").onclick = function() {
        self.set_time("sec"); return false;
    };
    document.getElementById("clear_button").onclick = function() {
        self.clear(); return false;
    };
}
