'use strict';

var simplesmtp = require('../index'),
    packageData = require('../package.json'),
    fs = require('fs');

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

var PORT_NUMBER = 8397;

exports['Version test'] = {
    'Should expose version number': function(test) {
        test.ok(simplesmtp.version);
        test.equal(simplesmtp.version, packageData.version);
        test.done();
    }
};

exports['General tests'] = {
    setUp: function(callback) {
        this.server = new simplesmtp.createServer();
        this.server.listen(PORT_NUMBER, function(err) {
            if (err) {
                throw err;
            } else {
                callback();
            }
        });

    },

    tearDown: function(callback) {
        this.server.end(callback);
    },

    'Connect and setup': function(test) {
        var client = simplesmtp.connect(PORT_NUMBER);

        client.once('idle', function() {
            // Client is ready to take messages
            test.ok(true);
            client.close();
        });

        client.on('error', function() {
            test.ok(false);
        });

        client.on('end', function() {
            test.done();
        });
    },

    'socketTimeout': function(test) {
        var client = simplesmtp.connect(PORT_NUMBER, false, {
            socketTimeout: 500
        });

        var waitTimeout = setTimeout(function() {
            test.ok(false);
            test.done();
        }, 2000);

        client.once('idle', function() {
            // Client is ready to take messages
            test.ok(true);
        });

        client.on('error', function(err) {
            test.ifError(err);
        });

        client.on('end', function() {
            clearTimeout(waitTimeout);
            test.done();
        });
    }
};

exports['Secure server'] = {
    setUp: function(callback) {
        this.server = new simplesmtp.createServer({
            secureConnection: true
        });
        this.server.listen(PORT_NUMBER, function(err) {
            if (err) {
                throw err;
            } else {
                callback();
            }
        });

    },

    tearDown: function(callback) {
        this.server.end(callback);
    },

    'Connect and setup': function(test) {
        var client = simplesmtp.connect(PORT_NUMBER, false, {
            secureConnection: true
        });

        client.once('idle', function() {
            // Client is ready to take messages
            test.ok(true);
            client.close();
        });

        client.on('error', function() {
            test.ok(false);
        });

        client.on('end', function() {
            test.done();
        });
    },

    'Unsecure client should have timeout': function(test) {
        var client = simplesmtp.connect(PORT_NUMBER, false, {
            secureConnection: false
        });

        client.once('idle', function() {
            test.ok(false);
        });

        client.on('error', function(err) {
            test.equal(err.code, 'ETIMEDOUT');
            client.close();
        });

        client.on('end', function() {
            test.done();
        });
    }
};

exports['Disabled EHLO'] = {
    setUp: function(callback) {
        this.server = new simplesmtp.createServer({
            disableEHLO: true
        });
        this.server.listen(PORT_NUMBER, function(err) {
            if (err) {
                throw err;
            } else {
                callback();
            }
        });

    },

    tearDown: function(callback) {
        this.server.end(callback);
    },

    'Connect and setup': function(test) {
        var client = simplesmtp.connect(PORT_NUMBER, false, {});

        client.once('idle', function() {
            // Client is ready to take messages
            test.ok(true);
            client.close();
        });

        client.on('error', function() {
            test.ok(false);
        });

        client.on('end', function() {
            test.done();
        });
    }
};

exports['Authentication needed'] = {
    setUp: function(callback) {
        this.server = new simplesmtp.createServer({
            requireAuthentication: true
        });

        this.server.on('authorizeUser', function(envelope, user, pass, callback) {
            callback(null, user == 'test1' && pass == 'test2');
        });

        this.server.listen(PORT_NUMBER, function(err) {
            if (err) {
                throw err;
            } else {
                callback();
            }
        });

    },

    tearDown: function(callback) {
        this.server.end(callback);
    },

    'Auth success': function(test) {
        var client = simplesmtp.connect(PORT_NUMBER, false, {
            auth: {
                user: 'test1',
                pass: 'test2'
            }
        });

        client.once('idle', function() {
            // Client is ready to take messages
            test.ok(true);
            client.close();
        });

        client.on('error', function() {
            test.ok(false);
        });

        client.on('end', function() {
            test.done();
        });
    },

    'Auth fails': function(test) {
        var client = simplesmtp.connect(PORT_NUMBER, false, {
            auth: {
                user: 'test3',
                pass: 'test4'
            }
        });

        client.once('idle', function() {
            // Client is ready to take messages
            test.ok(false); // should not occur
            client.close();
        });

        client.on('error', function() {
            test.ok(true); // login failed
        });

        client.on('end', function() {
            test.done();
        });
    }
};

exports['Message tests'] = {
    setUp: function(callback) {
        this.server = new simplesmtp.createServer({
            validateSender: true,
            validateRecipients: true
        });

        this.server.on('validateSender', function(envelope, email, callback) {
            callback(email != 'test@pangalink.net' ? new Error('Failed sender') : null);
        });

        this.server.on('validateRecipient', function(envelope, email, callback) {
            callback(email.split('@').pop() != 'pangalink.net' ? new Error('Failed recipient') : null);
        });

        this.server.on('dataReady', function(envelope, callback) {
            callback(null, 'ABC1'); // ABC1 is the queue id to be advertised to the client
            // callback(new Error('That was clearly a spam!'));
        });

        this.server.listen(PORT_NUMBER, function(err) {
            if (err) {
                throw err;
            } else {
                callback();
            }
        });

    },

    tearDown: function(callback) {
        this.server.end(callback);
    },

    'Set envelope success': function(test) {
        test.expect(2);

        var client = simplesmtp.connect(PORT_NUMBER, false, {});

        client.once('idle', function() {
            // Client is ready to take messages
            test.ok(true); // waiting for envelope

            client.useEnvelope({
                from: 'test@pangalink.net',
                to: [
                    'test1@pangalink.net',
                    'test2@pangalink.net'
                ]
            });
        });

        client.on('message', function() {
            // Client is ready to take messages
            test.ok(true); // waiting for message
            client.close();
        });

        client.on('error', function() {
            test.ok(false);
        });

        client.on('end', function() {
            test.done();
        });
    },

    'Set envelope fails for sender': function(test) {
        test.expect(2);

        var client = simplesmtp.connect(PORT_NUMBER, false, {});

        client.once('idle', function() {
            // Client is ready to take messages
            test.ok(true); // waiting for envelope

            client.useEnvelope({
                from: 'test3@pangalink.net',
                to: [
                    'test1@pangalink.net',
                    'test2@pangalink.net'
                ]
            });
        });

        client.on('message', function() {
            // Client is ready to take messages
            test.ok(false); // waiting for message
            client.close();
        });

        client.on('error', function() {
            test.ok(true);
        });

        client.on('end', function() {
            test.done();
        });
    },

    'Set envelope fails for receiver': function(test) {
        test.expect(2);

        var client = simplesmtp.connect(PORT_NUMBER, false, {});

        client.once('idle', function() {
            // Client is ready to take messages
            test.ok(true); // waiting for envelope

            client.useEnvelope({
                from: 'test@pangalink.net',
                to: [
                    'test1@kreata.ee',
                    'test2@kreata.ee'
                ]
            });
        });

        client.on('message', function() {
            // Client is ready to take messages
            test.ok(false); // waiting for message
            client.close();
        });

        client.on('error', function() {
            test.ok(true);
        });

        client.on('end', function() {
            test.done();
        });
    },

    'Set envelope partly fails': function(test) {
        test.expect(3);

        var client = simplesmtp.connect(PORT_NUMBER, false, {});

        client.once('idle', function() {
            // Client is ready to take messages
            test.ok(true); // waiting for envelope

            client.useEnvelope({
                from: 'test@pangalink.net',
                to: [
                    'test1@pangalink.net',
                    'test2@kreata.ee'
                ]
            });
        });

        client.on('rcptFailed', function() {
            // Client is ready to take messages
            test.ok(true); // waiting for message
        });

        client.on('message', function() {
            // Client is ready to take messages
            test.ok(true); // waiting for message
            client.close();
        });

        client.on('error', function() {
            test.ok(false);
        });

        client.on('end', function() {
            test.done();
        });
    },

    'Send message success': function(test) {
        test.expect(3);

        var client = simplesmtp.connect(PORT_NUMBER, false, {});

        client.once('idle', function() {
            // Client is ready to take messages
            test.ok(true); // waiting for envelope

            client.useEnvelope({
                from: 'test@pangalink.net',
                to: [
                    'test1@pangalink.net',
                    'test2@pangalink.net'
                ]
            });
        });

        client.on('message', function() {
            // Client is ready to take messages
            test.ok(true); // waiting for message

            client.write('From: abc@pangalink.net\r\nTo:cde@pangalink.net\r\nSubject: test\r\n\r\nHello World!');
            client.end();
        });

        client.on('ready', function(success) {
            test.ok(success);
            client.close();
        });

        client.on('error', function() {
            test.ok(false);
        });

        client.on('end', function() {
            test.done();
        });
    },

    'Stream message': function(test) {
        test.expect(3);

        var client = simplesmtp.connect(PORT_NUMBER, false, {});

        client.once('idle', function() {
            // Client is ready to take messages
            test.ok(true); // waiting for envelope

            client.useEnvelope({
                from: 'test@pangalink.net',
                to: [
                    'test1@pangalink.net',
                    'test2@pangalink.net'
                ]
            });
        });

        client.on('message', function() {
            // Client is ready to take messages
            test.ok(true); // waiting for message

            // pipe file to client
            fs.createReadStream(__dirname + '/testmessage.eml').pipe(client);
        });

        client.on('ready', function(success) {
            test.ok(success);
            client.close();
        });

        client.on('error', function() {
            test.ok(false);
        });

        client.on('end', function() {
            test.done();
        });
    }
};