let assert = require('assert');
import Crashreporter from '../crashreporter';
import Settings from "../settings";

let old_console = console;
let listeners:  NodeJS.UncaughtExceptionListener[] = [];
let removeListeners = function(){
    listeners = process.listeners("uncaughtException");
    process.removeAllListeners("uncaughtException");
}
let restoreListeners = function(){
    process.removeAllListeners("uncaughtException");
    listeners.forEach(listener => {
        process.on('uncaughtException', <any>listener);
    });
}

describe('crashreporter', function () {
    beforeEach(function(){
        Settings.Instance.setCrashReporter("global", {
            exitOnCrash: false
        });
    });
    afterEach(function(){
        console.error = old_console.error;
    });
    it("regular case", function(done){
        let i = 0;
        let old_exit = process.exit;
        process.exit = <any>function(code?: number){
            process.exit = old_exit;
            done("Exit was called");
        }
        console.error = function(message?: any, ...optionalParams: any[]){
            switch(i){
                case 0:
                    assert.equal(message, "Crash written in: %s");
                    assert.notEqual(optionalParams, null);
                    assert.equal(optionalParams.length, 1);
                break;
                case 1:
                    assert.notEqual(message, "");
                    assert.notEqual(message, null);
                    assert.notEqual(optionalParams, null);
                    assert.equal(optionalParams.length, 0);
                    setTimeout(function(){
                        process.exit = old_exit;
                        done();
                    }, 100);
                break;
            }
            i++;
        }

        removeListeners();
        let crash = new Crashreporter();
        process.emit("uncaughtException", new Error("Test"));
        restoreListeners();
    });

    it("try to exit on crash", function(done){
        Settings.Instance.setCrashReporter("global", {
            exitOnCrash: true
        });
        let old_exit = process.exit;
        process.exit = <any>function(code?: number){
            process.exit = old_exit;
            assert.equal(code, 1);
            done();
        }

        removeListeners();
        let crash = new Crashreporter();
        process.emit("uncaughtException", new Error("Test"));
        restoreListeners();
    });

    it("invalid mail crash", function(done){
        Settings.Instance.setCrashReporter("global", {
            exitOnCrash: true,
            mailEnabled: true
        });
        let i = 0;
        let old_exit = process.exit;
        process.exit = <any>function(code?: number){
            process.exit = old_exit;
            assert.equal(code, 1);
            assert.equal(i, 4);
            done();
        }
        console.error = function(message?: any, ...optionalParams: any[]){
            switch(i){
                case 0:
                    assert.equal(message, "Crash written in: %s");
                    assert.notEqual(optionalParams, null);
                    assert.equal(optionalParams.length, 1);
                break;
                case 1:
                    assert.notEqual(message, "");
                    assert.notEqual(message, null);
                    assert.notEqual(optionalParams, null);
                    assert.equal(optionalParams.length, 0);
                break;
                case 2:
                    assert.equal(message, '\n-------------------\ncrashreporter Error\n-------------------');
                    assert.notEqual(optionalParams, null);
                    assert.equal(optionalParams.length, 0);
                break;
                case 3:
                    assert.notEqual(message, "");
                    assert.notEqual(message, null);
                    assert.notEqual(optionalParams, null);
                    assert.equal(optionalParams.length, 0);
                break;
            }
            i++;
        }

        removeListeners();
        let crash = new Crashreporter();
        process.emit("uncaughtException", new Error("Test"));
        restoreListeners();
    });

    it("invalid mail crash don't exit", function(done){
        Settings.Instance.setCrashReporter("global", {
            exitOnCrash: false,
            mailEnabled: true
        });
        let i = 0;
        let old_exit = process.exit;
        process.exit = <any>function(code?: number){
            process.exit = old_exit;
            done("Exit was called");
        }
        console.error = function(message?: any, ...optionalParams: any[]){
            switch(i){
                case 0:
                    assert.equal(message, "Crash written in: %s");
                    assert.notEqual(optionalParams, null);
                    assert.equal(optionalParams.length, 1);
                break;
                case 1:
                    assert.notEqual(message, "");
                    assert.notEqual(message, null);
                    assert.notEqual(optionalParams, null);
                    assert.equal(optionalParams.length, 0);
                break;
                case 2:
                    assert.equal(message, '\n-------------------\ncrashreporter Error\n-------------------');
                    assert.notEqual(optionalParams, null);
                    assert.equal(optionalParams.length, 0);
                break;
                case 3:
                    assert.notEqual(message, "");
                    assert.notEqual(message, null);
                    assert.notEqual(optionalParams, null);
                    assert.equal(optionalParams.length, 0);

                    setTimeout(function(){
                        process.exit = old_exit;
                        done();
                    }, 100);
                break;
            }
            i++;
        }

        removeListeners();
        let crash = new Crashreporter();
        process.emit("uncaughtException", new Error("Test"));
        restoreListeners();
    });

    
});