var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
///<reference path="ecmascript-api.d.ts" />
///<reference path="console.d.ts" />
///<reference path="node.d.ts" />
var path = require("path");
var fs = require("fs");
var events = require("events");


var Paths = (function () {
    function Paths() {
        var path = require("path");
        this.bin = process.cwd();
        this.base = path.join(this.bin, "..");
        this.src = path.join(this.base, "src");
        this.ts = path.join(this.src, "ts");
        this.js = path.join(this.src, "js");
        this.doc = path.join(this.base, "doc");
        this.lib = path.join(this.base, "lib");
    }
    return Paths;
})();
var Config = (function () {
    function Config() {
        this.paths = new Paths();
    }
    return Config;
})();

var Task = (function (_super) {
    __extends(Task, _super);
    function Task(config, name) {
        _super.call(this);
        this.config = config;
        if (name === undefined) {
            if (this["constructor"] && this["constructor"].name)
                this.name = this["constructor"].name; else
                this.name = "Undefined Task";
        } else
            this.name = name;

        this.init();
    }
    Task.prototype.run = function () {
        this.emit("done");
        return true;
    };

    Task.prototype.init = function () {
    };
    return Task;
})(events.EventEmitter);

var CompileTask = (function (_super) {
    __extends(CompileTask, _super);
    function CompileTask() {
        _super.apply(this, arguments);
    }
    CompileTask.prototype.run = function () {
        var _this = this;
        this.old_dir = process.cwd();
        process.chdir(this.config.paths.ts);
        var cp = require("child_process");
        var cmd = "tsc @build.txt";
        if (this.comment)
            cmd += " -c";

        if (this.dist)
            cmd += " -out \"" + this.dist + "\"";

        if (this.declaration)
            cmd += " --declaration";

        cp.exec(cmd, function (error, stdout, stderr) {
            process.chdir(_this.old_dir);
            if (error) {
                console.error("build error: " + error);
                _this.emit("error", error);
                return;
            }

            _this.emit("done");
        });
        return true;
    };
    return CompileTask;
})(Task);

//TODO: ��ŁBjsdoc�ł�ʂ����H�ł�^��񂪎���ꂿ�Ⴄ�񂾂�ȁB
var DocumentTask = (function (_super) {
    __extends(DocumentTask, _super);
    function DocumentTask() {
        _super.apply(this, arguments);
    }
    DocumentTask.prototype.run = function () {
        //nothing todo
        this.emit("done");
        return true;
    };
    return DocumentTask;
})(Task);

var UnlinkTask = (function (_super) {
    __extends(UnlinkTask, _super);
    function UnlinkTask() {
        _super.apply(this, arguments);
    }
    UnlinkTask.prototype.run = function () {
        var _this = this;
        this.targets = this.targets ? this.targets : [this.target];
        this.cnt = 0;
        this.targets.forEach(function (target) {
            _this.process(target);
        });
        return true;
    };
    UnlinkTask.prototype.process = function (path) {
        var _this = this;
        fs.unlink(path, function (error) {
            if (_this._exit)
                return;

            if (error) {
                _this._exit = true;
                console.error("Can not delete " + path);
                _this.emit("error", error);
            } else {
                _this.cnt++;
                if (_this.cnt == _this.targets.length) {
                    _this._exit = true;
                    _this.emit("done");
                }
            }
        });
    };
    return UnlinkTask;
})(Task);

var CopyTask = (function (_super) {
    __extends(CopyTask, _super);
    function CopyTask() {
        _super.apply(this, arguments);
    }
    CopyTask.prototype.run = function () {
        var _this = this;
        var fs = require("fs");
        var rd = fs.createReadStream(this.src);
        var wr = fs.createWriteStream(this.dist);
        rd.on("error", function (error) {
            _this.emit("error", error);
        });
        wr.on("error", function (error) {
            _this.emit("error", error);
        });
        wr.on("close", function (ex) {
            if (!_this.remove) {
                _this.emit("done");
                return;
            }
            var unlink = new UnlinkTask(_this.config);
            unlink.target = _this.src;
            unlink.on("error", function (error) {
                _this.emit("error", error);
            });
            unlink.on("done", function () {
                _this.emit("done");
            });
            unlink.run();
        });
        rd.pipe(wr);
        return true;
    };
    return CopyTask;
})(Task);

var MinifiedTask = (function (_super) {
    __extends(MinifiedTask, _super);
    function MinifiedTask() {
        _super.apply(this, arguments);
    }
    MinifiedTask.prototype.run = function () {
        var _this = this;
        var UglifyJS = require("uglify-js");
        var result = UglifyJS.minify(this.src);

        var fs = require("fs");
        var wr = fs.createWriteStream(this.dist);
        wr.on("error", function (error) {
            _this.emit("error", error);
        });
        wr.on("close", function (ex) {
            _this.emit("done");
        });

        wr.write(result.code);
        wr.end();

        return true;
    };
    return MinifiedTask;
})(Task);

var DeployTask = (function (_super) {
    __extends(DeployTask, _super);
    function DeployTask() {
        _super.apply(this, arguments);
    }
    DeployTask.prototype.run = function () {
        var fs = require("fs");
        this.sub_tasks = [];
        var jgame_js = new CopyTask(this.config);
        jgame_js.src = path.join(this.config.paths.js, "jgame.js");
        jgame_js.dist = path.join(this.config.paths.base, "jgame.js");

        var jgame_d_ts = new CopyTask(this.config);
        jgame_d_ts.src = path.join(this.config.paths.ts, "jgame.d.ts");
        jgame_d_ts.dist = path.join(this.config.paths.lib, "jgame.d.ts");
        jgame_d_ts.remove = true;

        var jgame_min_js = new MinifiedTask(this.config);
        jgame_min_js.src = path.join(this.config.paths.js, "jgame.js");
        jgame_min_js.dist = path.join(this.config.paths.base, "jgame.min.js");

        this.sub_tasks.push(jgame_js);
        this.sub_tasks.push(jgame_d_ts);
        this.sub_tasks.push(jgame_min_js);

        for (var i = 0; i < this.sub_tasks.length; i++)
            this.processTask(this.sub_tasks[i]);

        return true;
    };

    DeployTask.prototype.processTask = function (task) {
        var _this = this;
        task.on("error", function (error) {
            if (_this._exit)
                return;
            _this._exit = true;
            var mes = task.name + " error: " + error;
            console.error(mes);
            _this.emit("error", mes);
        });

        task.on("done", function (error) {
            console.log("done!" + task.name + "," + task["src"]);
            if (_this._exit)
                return;
            _this.sub_tasks.splice(_this.sub_tasks.indexOf(task), 1);
            if (_this.sub_tasks.length == 0) {
                _this._exit = true;
                _this.emit("done");
            }
        });

        return task.run();
    };
    return DeployTask;
})(Task);

var TaskManager = (function (_super) {
    __extends(TaskManager, _super);
    function TaskManager() {
        _super.apply(this, arguments);
    }
    TaskManager.prototype.init = function () {
        this.tasks = [];
    };

    TaskManager.prototype.addTask = function (task) {
        this.tasks.push(task);
    };

    TaskManager.prototype._finishTask = function (task) {
        console.timeEnd(task.name);
        console.log("--------------------");
        console.log(" ");
        this.nextTask();
    };

    TaskManager.prototype.nextTask = function () {
        var _this = this;
        if (this.tasks.length == this.taskIndex) {
            this.emit("done", true);
            return false;
        }

        var task = this.tasks[this.taskIndex++];
        console.time(task.name);
        console.log("-----" + task.name + "-----");
        task.on("done", function () {
            _this._finishTask(task);
        });
        task.on("error", function () {
            console.error(task.name + " is error");
            _this._finishTask(task);
        });
        return task.run();
    };

    TaskManager.prototype.run = function () {
        this.taskIndex = 0;
        if (this.tasks.length == 0) {
            throw "no task";
        }
        this.nextTask();
        return true;
    };
    return TaskManager;
})(Task);

var main = function () {
    var argv = require("argv");
    argv.info("jgame.js builder\nSupported only \"node build deploy\" command.");
    argv.version("1.0");
    var args = argv.run();
    var mode = args.targets.length > 0 ? args.targets[0] : null;

    var modes = {
        deploy: []
    };
    if (!mode || !modes[mode]) {
        argv.help();
        return;
    }

    var config = new Config();
    var compiler = new CompileTask(config, "TypeScript Compiler");
    var define = new CompileTask(config, "Define Builder");
    define.dist = path.join(config.paths.ts, "jgame.js");
    define.declaration = true;
    define.comment = true;
    modes.deploy.push(compiler);
    modes.deploy.push(define);
    modes.deploy.push(new DeployTask(config, "Publisher"));
    modes.deploy.push(new DocumentTask(config, "Document Generator"));
    var cleaner = new UnlinkTask(config, "Cleaner");
    cleaner.targets = [
        path.join(config.paths.ts, "jgame.js")
    ];
    modes.deploy.push(cleaner);

    var manager = new TaskManager(config);
    for (var i = 0; i < modes[mode].length; i++) {
        var task = modes[mode][i];
        manager.addTask(task);
    }

    manager.run();
    manager.on("done", function () {
        console.error("finished.");
    });
    manager.on("error", function () {
        console.error("stopped.");
    });
};
main();

//@ sourceMappingURL=build.js.map
