import { jQuery } from "../core.js";

import "../ajax.js";

jQuery.ajaxSettings.xhr = function() {
	return new window.XMLHttpRequest();
};

var xhrSuccessStatus = {

	// File protocol always yields status code 0, assume 200
	0: 200
};

jQuery.ajaxTransport( function( options ) {
	var callback;

	return {
		send: function( headers, complete ) {
			var i,
				xhr = options.xhr();

			xhr.open(
				options.type,
				options.url,
				options.async,
				options.username,
				options.password
			);

			// Apply custom fields if provided
			if ( options.xhrFields ) {
				for ( i in options.xhrFields ) {
					xhr[ i ] = options.xhrFields[ i ];
				}
			}

			// Override mime type if needed
			if ( options.mimeType && xhr.overrideMimeType ) {
				xhr.overrideMimeType( options.mimeType );
			}

			// X-Requested-With header
			// For cross-domain requests, seeing as conditions for a preflight are
			// akin to a jigsaw puzzle, we simply never set it to be sure.
			// (it can always be set on a per-request basis or even using ajaxSetup)
			// For same-domain requests, won't change header if already provided.
			if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
				headers[ "X-Requested-With" ] = "XMLHttpRequest";
			}

			// Set headers
			for ( i in headers ) {
				xhr.setRequestHeader( i, headers[ i ] );
			}

			// Callback
			callback = function( type ) {
				return function() {
					if ( callback ) {
						callback = xhr.onload = xhr.onerror = xhr.onabort = xhr.ontimeout = null;

						if ( type === "abort" ) {
							xhr.abort();
						} else if ( type === "error" ) {
							complete(

								// File: protocol always yields status 0; see trac-8605, trac-14207
								xhr.status,
								xhr.statusText
							);
						} else {
							complete(
								xhrSuccessStatus[ xhr.status ] || xhr.status,
								xhr.statusText,

								// For XHR2 non-text, let the caller handle it (gh-2498)
								( xhr.responseType || "text" ) === "text" ?
									{ text: xhr.responseText } :
									{ binary: xhr.response },
								xhr.getAllResponseHeaders()
							);
						}
					}
				};
			};

			// Listen to events
			xhr.onload = callback();
			xhr.onabort = xhr.onerror = xhr.ontimeout = callback( "error" );

			// Create the abort callback
			callback = callback( "abort" );

			try {

				// Do send the request (this may raise an exception)
				xhr.send( options.hasContent && options.data || null );
			} catch ( e ) {

				// trac-14683: Only rethrow if this hasn't been notified as an error yet
				if ( callback ) {
					throw e;
				}
			}
		},

		abort: function() {
			if ( callback ) {
				callback();
			}
		}
	};
} );
