/**
 * @author Jonathan Cardoso Machado
 * @license MIT
 * @copyright 2015, Jonathan Cardoso Machado
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
/**
 * yay this has code from the httppost and postfields test cases.
 * this is because the duplicated handle shares the ToFree instance of the original handle
 * and this object is used to keep data around for libcurl, and this data is exactly
 * the data used by HTTPPOST and POSTFIELDS.
 */
var fs     = require( 'fs' ),
    path   = require( 'path' ),
    multiparty  = require( 'multiparty' ),
    querystring = require( 'querystring' ),
    serverObj   = require( './../helper/server' ),
    Curl     = require( '../../lib/Curl' );

var server = serverObj.server,
    app    = serverObj.app,
    curl   = new Curl(),
    image  = ' ',
    imageFilename = path.resolve( __dirname, 'upload.png' ),
    buff = new Buffer( image, 'base64' ),
    httpPostData = [{
        name     : 'file',
        file     : imageFilename,
        type     : 'image/png'
    }],
    postFieldsData = {
        'input-name' : 'This is input-name value.',
        'input-name2': 'This is input-name2 value'
    },
    size = buff.length,
    url, duplicatedCurl;

beforeEach( function() {

    curl = new Curl();
    curl.setOpt( 'URL', url );
});

afterEach( function() {

    if ( curl ) {
        curl.close();
    }

    if ( duplicatedCurl ) {
        duplicatedCurl.close();
    }
});

before( function( done ) {

    server.listen( serverObj.port, serverObj.host, function() {

        url = server.address().address + ':' + server.address().port;

        fs.writeFile( imageFilename, buff, done );
    });

    app.post( '/urlencoded', function( req, res ) {

        res.send( JSON.stringify( req.body ) );
    });

    app.post( '/multipart', function( req, res ) {

        // parse a file upload
        var form = new multiparty.Form();

        form.parse( req, function( err, fields, files ) {

            if ( err ) {
                throw err;
            }

            var file = files.file;

            var response = {
                size : file[0].size,
                name : file[0].originalFilename,
                type : file[0].headers['content-type']
            };

            res.send( JSON.stringify( response ) );
        });
    });
});

after( function( done ) {

    server.close();

    app._router.stack.pop();
    app._router.stack.pop();

    fs.unlink( imageFilename, done );
});

it( 'should correctly send HTTPPOST data when duplicated', function ( done ) {

    curl.setOpt( 'HTTPPOST', httpPostData );
    curl.setOpt( 'URL', url + '/multipart' );

    duplicatedCurl = curl.dupHandle();

    duplicatedCurl.on( 'end', function( status, data ) {

        if ( status !== 200 ) {
            throw Error( 'Invalid status code: ' + status );
        }

        data = JSON.parse( data );

        data.size.should.be.equal( size );
        data.name.should.be.equal( imageFilename.split( path.sep ).pop() );
        data.type.should.be.equal( httpPostData[0].type );

        done();
    });

    duplicatedCurl.on( 'error', function( err ) {

        done( err );
    });

    duplicatedCurl.perform();

});

it( 'should correctly send POSTFIELDS data when duplicated', function ( done ) {

    curl.setOpt( 'POSTFIELDS', querystring.stringify( postFieldsData ) );
    curl.setOpt( 'URL', url + '/urlencoded' );

    duplicatedCurl = curl.dupHandle();

    duplicatedCurl.on( 'end', function( status, data ) {

        if ( status !== 200 ) {
            throw Error( 'Invalid status code: ' + status );
        }

        data = JSON.parse( data );

        for ( var field in data ) {

            if ( data.hasOwnProperty( field ) ) {

                data[field].should.be.equal( postFieldsData[field] );
            }
        }

        done();
    });

    duplicatedCurl.on( 'error', function( err ) {

        done( err );
    });

    duplicatedCurl.perform();
});


it( 'should correctly send HTTPPOST data when duplicated and the original closed', function ( done ) {

    curl.setOpt( 'HTTPPOST', httpPostData );
    curl.setOpt( 'URL', url + '/multipart' );

    duplicatedCurl = curl.dupHandle();

    curl.close();
    curl = null;

    duplicatedCurl.on( 'end', function( status, data ) {

        if ( status !== 200 ) {
            throw Error( 'Invalid status code: ' + status );
        }

        data = JSON.parse( data );

        data.size.should.be.equal( size );
        data.name.should.be.equal( imageFilename.split( path.sep ).pop() );
        data.type.should.be.equal( httpPostData[0].type );

        done();
    });

    duplicatedCurl.on( 'error', function( err ) {

        done( err );
    });

    duplicatedCurl.perform();

});

it( 'should correctly send POSTFIELDS data when duplicated and the original closed', function ( done ) {

    curl.setOpt( 'POSTFIELDS', querystring.stringify( postFieldsData ) );
    curl.setOpt( 'URL', url + '/urlencoded' );

    duplicatedCurl = curl.dupHandle();

    curl.close();
    curl = null;

    duplicatedCurl.on( 'end', function( status, data ) {

        if ( status !== 200 ) {
            throw Error( 'Invalid status code: ' + status );
        }

        data = JSON.parse( data );

        for ( var field in data ) {

            if ( data.hasOwnProperty( field ) ) {

                data[field].should.be.equal( postFieldsData[field] );
            }
        }

        done();
    });

    duplicatedCurl.on( 'error', function( err ) {

        done( err );
    });

    duplicatedCurl.perform();
});
