var irc = require('irc'),
    _ = require('underscore');

var IRCActor = function(actorConfig, globalConfig){
    return {
        onStage: false,
        setup: function(clb){
            console.log(new Date().toString(), 'actor::setup', actorConfig.nickName);
            this.client = new irc.Client(globalConfig.irc.server, actorConfig.nickName, {
                userName: actorConfig.id,
                realName: actorConfig.name,
                port: 6667,
                debug: false,
                showErrors: false,
                autoRejoin: true,
                autoConnect: true,
                secure: false
            });
            this.client.addListener('connect', clb);
        },
        enter: function(clb) {
            console.log(new Date().toString(), "actor::enter", actorConfig.id, globalConfig.irc.channel);
            var that = this;
            if (this.onStage) {
                clb();
            } else {
                console.log(new Date().toString(), 'irc::join', actorConfig.id, globalConfig.irc.channel)
                this.client.join(globalConfig.irc.channel, function(){
                    that.onStage = true;
                    clb();
                });
            }
        },
        speak: function(statement, clb) {
            console.log(new Date().toString(), "actor::speak", actorConfig.id);
            var that = this;
            if (!this.onStage){
                this.enter(function(){
                    that.speak(statement, clb);
                });
            }
            console.log(new Date().toString(), "irc::say", actorConfig.id, globalConfig.irc.channel, statement.line);
            this.client.say(globalConfig.irc.channel, statement.line);
            var timeout = statement.line.split(' ').length * 600 + 1000;
            setTimeout(clb, timeout);
        },
        exit: function(clb){
            console.log(new Date().toString(), 'actor::exit', actorConfig.id)
            var that = this;
            if (!this.onStage) {
                clb();
            } else {
                console.log(new Date().toString(), 'irc::part', globalConfig.irc.channel)
                this.client.part(globalConfig.irc.channel, function() {
                    that.onStage = false;
                    clb();
                });
            }
        }
    };
};

exports.getTheater = function(){
    return {
        setup: function(config, clb){
            console.log(new Date().toString(), 'theater::setup')
            var that = this;
            this.actors = {};
            this.config = config;
            this.director =  new irc.Client(config.irc.server, config.prefix + "director", {
                userName: 'nodeshakespearebot',
                realName: 'Director',
                port: 6667,
                debug: false,
                showErrors: false,
                autoRejoin: true,
                autoConnect: true,
                secure: false
            });
            this.director.addListener('connect', function() {
                that.director.join(that.config.irc.channel, function() {
                    var cb = _.after(config.actors.length, clb);
                    config.actors.forEach(function(actor) {
                        that.actors[actor.id] = IRCActor(actor, config);
                        that.actors[actor.id].setup(cb);
                    });
                });
            });
        },
        run: function(skript) {
            console.log(new Date().toString(), 'theater::run')
            var current = 0, that = this, lastActor;
            that.director.addListener("message" + this.config.irc.channel, function(from, message){
                console.log(new Date().toString(), 'director got:', message, 'from:', from);
            });
            // should be called executeAndNextAndNextAndNext..
            var executeNext = function() {
                console.log(new Date().toString(), 'theater::run::executeNext', current);
                if (!_.isUndefined(skript[current])) {
                    that.execute(skript[current], function() {
                        current += 1;
                        executeNext();
                    });
                } else {
                    that.tearDown();
                }
            };
            executeNext();
        },
        execute: function(statement, clb) {
            console.log(new Date().toString(), 'theater::execute', statement)
            if (_.isFunction(this[statement.action])) {
                this[statement.action](statement, clb);
            }
        },
        announcement: function(data, clb){
            this.director.say(this.config.irc.channel, data.content);
            setTimeout(clb, 2000);
        },
        forActorsDo: function(actorsIds, action, clb) {
            var that = this,
                cb = _.after(actorsIds.length, clb);
            actorsIds.forEach(function(id) {
                that.actors[id][action](cb);
            });
        },
        enter: function(data, clb) {
            this.forActorsDo(data.actors, "enter", clb);
        },
        speak: function(data, clb) {
            this.actors[data.actor].speak(data, clb);
        },
        exit: function(data, clb) {
            this.forActorsDo(data.actors, "exit", clb);
        },
        tearDown: function() {
            console.log(new Date().toString(), 'theater::teardown');
            _(this.actors).chain()
                .values()
                .filter(function(actor) { return actor.onStage; })
                .each(function(actor) { actor.exit(function(){}); })
        }
    };
};

@@ -1043,33 +1043,34 @@
 fig.irc.channel)
+;
 %0A
-
                 
@@ -1958,16 +1958,17 @@
 nfig.id)
+;
 %0A       
@@ -2155,16 +2155,17 @@
 channel)
+;
 %0A       
@@ -2501,16 +2501,17 @@
 :setup')
+;
 %0A       
@@ -3538,16 +3538,17 @@
 r::run')
+;
 %0A       
@@ -4386,32 +4386,32 @@
 atement, clb) %7B%0A
-
             cons
@@ -4471,16 +4471,17 @@
 atement)
+;
 %0A       

fix semicolons and no actors in channel by default