window.getEpisode = function() {
	return window.episode;
};

var Episode = Class.create();
Episode.prototype = {
	initialize: function(showId, episodeId, status) {
        this.avoidFirstAjaxCall = true;
		this.showId = showId;
		this.episodeId = episodeId;
        this.chatData = {
            shw_id: showId,
            epi_id: episodeId
        }
        this.setStatus(status);
	},
    setStatus: function(status) {
        if (this.status)
            this.status.episode = null;
        this.status = status;
        this.status.episode = this;
        this.status.start();
    },
    setData: function(data) {
        $H(data).each(function(pair) {
            this.chatData[pair.first()] = pair.last();
        }.bind(this));
        return this;
    },
    onAir: function() { return this.status.onAir(); },
    offAir: function() { return this.status.offAir(); },
    setParticipants: function(participants) { return this.status.setParticipants(participants); },
    setViewers: function(viewers) { return this.status.setViewers(viewers); }
}

Abstract.Status = Class.create();
Abstract.Status.prototype = {
    initialize: function() {
        this.name = null;
        this.episode = null;
        this.updater = null;
        this.onUpdateInterval = this.update;
    },
    startUpdater: function(method) {
        method = method === undefined ? this.onUpdateInterval : method;
        this.updater = new PeriodicalExecuter(method.bind(this), 30);
    },
    start: function() {
        if (this.episode.avoidFirstAjaxCall) {
            this.episode.avoidFirstAjaxCall = false;
            return false;
        }
        new Ajax.Request(document.location.href + "/about" + (this.name ? "/" + this.name : ""), { 
            method: "get", 
            parameters: { t: Date.now().getTime() },
            onComplete: function(request) {
                $("about").replace(request.responseText);
            }.bind(this)
        });
        return true;
    }
}

Episode.Scheduled = Class.create();
Episode.Scheduled.prototype = Object.extend(new Abstract.Status(), {
    initialize: function(dateScheduled) {
        this.dateScheduled = new Date(dateScheduled);
        $("status").className = "scheduled";
        // this.startUpdater();
    },
    start: function() {
        if (this.canEnterStudio())
            return this.inStudio();
        Abstract.Status.prototype.start.apply(this);
    },
    inStudio: function() {
        // this.updater.stop();
        this.episode.setStatus(new Episode.Waiting(this.dateScheduled));
    },
    onUpdateInterval: function() {
        this.update();
        if (this.canEnterStudio()) {
            this.inStudio();
        }
    },
    canEnterStudio: function() {
        return this.dateScheduled.getTime() < (10).minutes().ago().getTime();
    },
    update: function() {
        $("status").update("<strong>Airing</strong> on " + this.dateScheduled.relativeTime());
        try {
            $("details").down(".date-scheduled span").update(this.dateScheduled.relativeTime());
        } catch(e) {}
    }
});

Episode.Waiting = Class.create();
Episode.Waiting.prototype = Object.extend(new Abstract.Status(), {
    name: "waiting",
    initialize: function(dateScheduled) {
        this.dateScheduled = new Date(dateScheduled);
        // this.startUpdater(this.poll);
        // this.update();
        // $("status").className = "scheduled";
        // if ($("externalChat")) 
        //    $("externalChat").id = "externalChatInactive";
    },
    onUpdateInterval: function(request) {
        this.update();
        if (this.isInStudio(request)) {
            this.updater.stop();
            this.episode.setStatus(new Episode.InStudio(this.dateScheduled));
        } else if (this.isLate()) {
            this.updater.stop();
            this.episode.setStatus(new Episode.Late(this.dateScheduled));
        }
    },
    isInStudio: function(request) {
        return parseInt(request.responseText) === 1;
    },
    isLate: function() {
        return this.dateScheduled.getTime() > (30).minutes().ago().getTime();
    },
    poll: function() {
        new Ajax.Request(this.episode.pollUrl, { 
            method: "get", 
            parameters: { t: Date.now().getTime() }, 
            onComplete: this.onUpdateInterval.bind(this) 
        });
    },
    update: function() {
		$("status").update("<strong>Waiting for the director!</strong> (should " + 
            (this.dateScheduled.inTheFuture() ? "start" : "have started") + " " + this.dateScheduled.relativeTime() + ")");
        try {
            $("details").down(".date-scheduled span").update(this.dateScheduled.relativeTime());
        } catch(e) {}
    }
});

Episode.Late = Class.create();
Episode.Late.prototype = Object.extend(new Abstract.Status(), {
    initialize: function(dateScheduled) {
        this.dateScheduled = new Date(dateScheduled);
        // this.onUpdateInterval = this.update;
        // this.startUpdater();
        // this.update();
        // $("status").className = "late";
    },
    update: function() {
        $("status").update("<strong>Show's late!</strong> Should have started " + this.dateScheduled.relativeTime());
        try {
            $("about").down(".date-scheduled span").update(this.dateScheduled.relativeTime());
        } catch(e) {}
    }
});

Episode.InStudio = Class.create();
Episode.InStudio.prototype = Object.extend(new Abstract.Status(), {
    initialize: function(dateScheduled, participants, viewers) {
        this.dateScheduled = new Date(dateScheduled);
        this.participants = parseInt(participants) || 1; // the director, at least
        this.viewers = parseInt(viewers) || 1;
        $("status").className = "about-to-begin";
        this.update();
    },
    start: function() {
            this.loadChat.bind(this).delay(1);
            Abstract.Status.prototype.start.apply(this);
    },
    setParticipants: function(participants) {
        this.participants = participants;
        this.update();
    },
    setViewers: function(viewers) {
        this.viewers = viewers;
        this.update();
    },
    onAir: function() {
        this.episode.setStatus(new Episode.OnAir(this.participants));
    },
    offAir: function() {
        this.episode.setStatus(new Episode.Waiting(this.dateScheduled));
    },
    loadChat: function() {
        if ($("externalChat"))
            return;
        if ($("externalChatInactive"))
            $("externalChatInactive").remove();
        $("player").insert(new Element("div", { id: "chat" }));
        var so = new SWFObject(this.episode.chatData["chat_path"], "externalChat", "432", "195", "8.0", "#fff", true);
        $H(this.episode.chatData).each(function(pair) {
            so.addVariable(pair.first(), pair.last());
        }.bind(this));
        so.addParam("allowScriptAccess", "always");
        so.write($("chat"));
    },
    unloadChat: function() {
        $("chat").update("");
    },
    update: function() {
        $("status").update("<strong>Show's about to begin!</strong> (" + pluralize(this.participants, 'person') + " in the studio)");
        try {
            $("details").down(".participants span").update(this.participants);
        } catch(e) {}
    }
});

Episode.OnAir = Class.create();
Episode.OnAir.prototype = new Abstract.Status();
Episode.OnAir.prototype = Object.extend(Episode.OnAir.prototype, Episode.InStudio.prototype);
Episode.OnAir.prototype = Object.extend(Episode.OnAir.prototype, {
    initialize: function(participants, viewers) {
        this.participants = parseInt(participants);
        this.viewers = parseInt(viewers) || 1;
        this.update();
        $("status").className = "on-air";
    },
    start: function() {
        if (Abstract.Status.prototype.start.apply(this)) {
            new Ajax.Updater("toolbar", "/shows/" + this.episode.showId + "/episodes/" + this.episode.episodeId + "/rate", { 
                method: "get", 
                evalScripts: true, 
                insertion: "bottom" 
            });
        }
        this.loadChat.bind(this).delay(1);
    },
    onAir: function() {},
    offAir: function() {
        new Ajax.Updater("director", "/shows/" + this.episode.showId + "/episodes/" + this.episode.episodeId + "/participants", {
            method: "get",
            parameters: { t: Date.now().getTime() },
            insertion: "after"
        });
        this.episode.setStatus(new Episode.Recorded());
    },
    update: function() {
        $("status").update("<strong>ON NET</strong> " + (this.participants) + " in the studio / " + this.viewers + " watching");
        try {
            $("details").down(".participants span").update(this.participants);
            $("details").down(".watching span").update(this.viewers);
        } catch (e) {}
    }
});

Episode.Recorded = Class.create();
Episode.Recorded.prototype = Object.extend(new Abstract.Status(), {
    name: "recorded",
    initialize: function() {
        var status = $("status");
        status && status.remove();
    }
});
