/**
 * XmlHttpRequest implementation that uses TLS and flash SocketPool.
 *
 * @author Dave Longley
 *
 * Copyright (c) 2010-2013 Digital Bazaar, Inc.
 */
(function($) {

// logging category
var cat = 'forge.xhr';

/*
XMLHttpRequest interface definition from:
http://www.w3.org/TR/XMLHttpRequest

interface XMLHttpRequest {
  // event handler
  attribute EventListener onreadystatechange;

  // state
  const unsigned short UNSENT = 0;
  const unsigned short OPENED = 1;
  const unsigned short HEADERS_RECEIVED = 2;
  const unsigned short LOADING = 3;
  const unsigned short DONE = 4;
  readonly attribute unsigned short readyState;

  // request
  void open(in DOMString method, in DOMString url);
  void open(in DOMString method, in DOMString url, in boolean async);
  void open(in DOMString method, in DOMString url,
            in boolean async, in DOMString user);
  void open(in DOMString method, in DOMString url,
            in boolean async, in DOMString user, in DOMString password);
  void setRequestHeader(in DOMString header, in DOMString value);
  void send();
  void send(in DOMString data);
  void send(in Document data);
  void abort();

  // response
  DOMString getAllResponseHeaders();
  DOMString getResponseHeader(in DOMString header);
  readonly attribute DOMString responseText;
  readonly attribute Document responseXML;
  readonly attribute unsigned short status;
  readonly attribute DOMString statusText;
};
*/

// readyStates
var UNSENT = 0;
var OPENED = 1;
var HEADERS_RECEIVED = 2;
var LOADING = 3;
var DONE = 4;

// exceptions
var INVALID_STATE_ERR = 11;
var SYNTAX_ERR = 12;
var SECURITY_ERR = 18;
var NETWORK_ERR = 19;
var ABORT_ERR = 20;

// private flash socket pool vars
var _sp = null;
var _policyPort = 0;
var _policyUrl = null;

// default client (used if no special URL provided when creating an XHR)
var _client = null;

// all clients including the default, key'd by full base url
// (multiple cross-domain http clients are permitted so there may be more
// than one client in this map)
// TODO: provide optional clean up API for non-default clients
var _clients = {};

// the default maximum number of concurrents connections per client
var _maxConnections = 10;

// local aliases
if(typeof forge === 'undefined') {
  forge = {};
}
var net = forge.net;
var http = forge.http;

// define the xhr interface
var xhrApi = {};

/**
 * Initializes flash XHR support.
 *
 * @param options:
 *   url: the default base URL to connect to if xhr URLs are relative,
 *     ie: https://myserver.com.
 *   flashId: the dom ID of the flash SocketPool.
 *   policyPort: the port that provides the server's flash policy, 0 to use
 *     the flash default.
 *   policyUrl: the policy file URL to use instead of a policy port.
 *   msie: true if browser is internet explorer, false if not.
 *   connections: the maximum number of concurrent connections.
 *   caCerts: a list of PEM-formatted certificates to trust.
 *   cipherSuites: an optional array of cipher suites to use,
 *     see forge.tls.CipherSuites.
 *   verify: optional TLS certificate verify callback to use (see forge.tls
 *     for details).
 *   getCertificate: an optional callback used to get a client-side
 *     certificate (see forge.tls for details).
 *   getPrivateKey: an optional callback used to get a client-side private
 *     key (see forge.tls for details).
 *   getSignature: an optional callback used to get a client-side signature
 *     (see forge.tls for details).
 *   persistCookies: true to use persistent cookies via flash local storage,
 *     false to only keep cookies in javascript.
 *   primeTlsSockets: true to immediately connect TLS sockets on their
 *     creation so that they will cache TLS sessions for reuse.
 */
xhrApi.init = function(options) {
  forge.log.debug(cat, 'initializing', options);

  // update default policy port and max connections
  _policyPort = options.policyPort || _policyPort;
  _policyUrl = options.policyUrl || _policyUrl;
  _maxConnections = options.connections || _maxConnections;

  // create the flash socket pool
  _sp = net.createSocketPool({
    flashId: options.flashId,
    policyPort: _policyPort,
    policyUrl: _policyUrl,
    msie: options.msie || false
  });

  // create default http client
  _client = http.createClient({
    url: options.url || (
      window.location.protocol + '//' + window.location.host),
    socketPool: _sp,
    policyPort: _policyPort,
    policyUrl: _policyUrl,
    connections: options.connections || _maxConnections,
    caCerts: options.caCerts,
    cipherSuites: options.cipherSuites,
    persistCookies: options.persistCookies || true,
    primeTlsSockets: options.primeTlsSockets || false,
    verify: options.verify,
    getCertificate: options.getCertificate,
    getPrivateKey: options.getPrivateKey,
    getSignature: options.getSignature
  });
  _clients[_client.url.full] = _client;

  forge.log.debug(cat, 'ready');
};

/**
 * Called to clean up the clients and socket pool.
 */
xhrApi.cleanup = function() {
  // destroy all clients
  for(var key in _clients) {
    _clients[key].destroy();
  }
  _clients = {};
  _client = null;

  // destroy socket pool
  _sp.destroy();
  _sp = null;
};

/**
 * Sets a cookie.
 *
 * @param cookie the cookie with parameters:
 *   name: the name of the cookie.
 *   value: the value of the cookie.
 *   comment: an optional comment string.
 *   maxAge: the age of the cookie in seconds relative to created time.
 *   secure: true if the cookie must be sent over a secure protocol.
 *   httpOnly: true to restrict access to the cookie from javascript
 *     (inaffective since the cookies are stored in javascript).
 *   path: the path for the cookie.
 *   domain: optional domain the cookie belongs to (must start with dot).
 *   version: optional version of the cookie.
 *   created: creation time, in UTC seconds, of the cookie.
 */
xhrApi.setCookie = function(cookie) {
  // default cookie expiration to never
  cookie.maxAge = cookie.maxAge || -1;

  // if the cookie's domain is set, use the appropriate client
  if(cookie.domain) {
    // add the cookies to the applicable domains
    for(var key in _clients) {
      var client = _clients[key];
      if(http.withinCookieDomain(client.url, cookie) &&
        client.secure === cookie.secure) {
        client.setCookie(cookie);
      }
    }
  } else {
    // use the default domain
    // FIXME: should a null domain cookie be added to all clients? should
    // this be an option?
    _client.setCookie(cookie);
  }
};

/**
 * Gets a cookie.
 *
 * @param name the name of the cookie.
 * @param path an optional path for the cookie (if there are multiple cookies
 *          with the same name but different paths).
 * @param domain an optional domain for the cookie (if not using the default
 *          domain).
 *
 * @return the cookie, cookies (if multiple matches), or null if not found.
 */
xhrApi.getCookie = function(name, path, domain) {
  var rval = null;

  if(domain) {
    // get the cookies from the applicable domains
    for(var key in _clients) {
      var client = _clients[key];
      if(http.withinCookieDomain(client.url, domain)) {
        var cookie = client.getCookie(name, path);
        if(cookie !== null) {
          if(rval === null) {
            rval = cookie;
          } else if(!forge.util.isArray(rval)) {
            rval = [rval, cookie];
          } else {
            rval.push(cookie);
          }
        }
      }
    }
  } else {
    // get cookie from default domain
    rval = _client.getCookie(name, path);
  }

  return rval;
};

/**
 * Removes a cookie.
 *
 * @param name the name of the cookie.
 * @param path an optional path for the cookie (if there are multiple cookies
 *          with the same name but different paths).
 * @param domain an optional domain for the cookie (if not using the default
 *          domain).
 *
 * @return true if a cookie was removed, false if not.
 */
xhrApi.removeCookie = function(name, path, domain) {
  var rval = false;

  if(domain) {
    // remove the cookies from the applicable domains
    for(var key in _clients) {
      var client = _clients[key];
      if(http.withinCookieDomain(client.url, domain)) {
        if(client.removeCookie(name, path)) {
           rval = true;
        }
      }
    }
  } else {
    // remove cookie from default domain
    rval = _client.removeCookie(name, path);
  }

  return rval;
};

/**
 * Creates a new XmlHttpRequest. By default the base URL, flash policy port,
 * etc, will be used. However, an XHR can be created to point at another
 * cross-domain URL.
 *
 * @param options:
 *   logWarningOnError: If true and an HTTP error status code is received then
 *     log a warning, otherwise log a verbose message.
 *   verbose: If true be very verbose in the output including the response
 *     event and response body, otherwise only include status, timing, and
 *     data size.
 *   logError: a multi-var log function for warnings that takes the log
 *     category as the first var.
 *   logWarning: a multi-var log function for warnings that takes the log
 *     category as the first var.
 *   logDebug: a multi-var log function for warnings that takes the log
 *     category as the first var.
 *   logVerbose: a multi-var log function for warnings that takes the log
 *     category as the first var.
 *   url: the default base URL to connect to if xhr URLs are relative,
 *     eg: https://myserver.com, and note that the following options will be
 *     ignored if the URL is absent or the same as the default base URL.
 *   policyPort: the port that provides the server's flash policy, 0 to use
 *     the flash default.
 *   policyUrl: the policy file URL to use instead of a policy port.
 *   connections: the maximum number of concurrent connections.
 *   caCerts: a list of PEM-formatted certificates to trust.
 *   cipherSuites: an optional array of cipher suites to use, see
 *     forge.tls.CipherSuites.
 *   verify: optional TLS certificate verify callback to use (see forge.tls
 *     for details).
 *   getCertificate: an optional callback used to get a client-side
 *     certificate.
 *   getPrivateKey: an optional callback used to get a client-side private key.
 *   getSignature: an optional callback used to get a client-side signature.
 *   persistCookies: true to use persistent cookies via flash local storage,
 *     false to only keep cookies in javascript.
 *   primeTlsSockets: true to immediately connect TLS sockets on their
 *     creation so that they will cache TLS sessions for reuse.
 *
 * @return the XmlHttpRequest.
 */
xhrApi.create = function(options) {
  // set option defaults
  options = $.extend({
    logWarningOnError: true,
    verbose: false,
    logError: function(){},
    logWarning: function(){},
    logDebug: function(){},
    logVerbose: function(){},
    url: null
  }, options || {});

  // private xhr state
  var _state = {
    // the http client to use
    client: null,
    // request storage
    request: null,
    // response storage
    response: null,
    // asynchronous, true if doing asynchronous communication
    asynchronous: true,
    // sendFlag, true if send has been called
    sendFlag: false,
    // errorFlag, true if a network error occurred
    errorFlag: false
  };

  // private log functions
  var _log = {
    error: options.logError || forge.log.error,
    warning: options.logWarning || forge.log.warning,
    debug: options.logDebug || forge.log.debug,
    verbose: options.logVerbose || forge.log.verbose
  };

  // create public xhr interface
  var xhr = {
    // an EventListener
    onreadystatechange: null,
    // readonly, the current readyState
    readyState: UNSENT,
    // a string with the response entity-body
    responseText: '',
    // a Document for response entity-bodies that are XML
    responseXML: null,
    // readonly, returns the HTTP status code (i.e. 404)
    status: 0,
    // readonly, returns the HTTP status message (i.e. 'Not Found')
    statusText: ''
  };

  // determine which http client to use
  if(options.url === null) {
    // use default
    _state.client = _client;
  } else {
    var url = http.parseUrl(options.url);
    if(!url) {
      var error = new Error('Invalid url.');
      error.details = {
        url: options.url
      };
    }

    // find client
    if(url.full in _clients) {
      // client found
      _state.client = _clients[url.full];
    } else {
      // create client
      _state.client = http.createClient({
        url: options.url,
        socketPool: _sp,
        policyPort: options.policyPort || _policyPort,
        policyUrl: options.policyUrl || _policyUrl,
        connections: options.connections || _maxConnections,
        caCerts: options.caCerts,
        cipherSuites: options.cipherSuites,
        persistCookies: options.persistCookies || true,
        primeTlsSockets: options.primeTlsSockets || false,
        verify: options.verify,
        getCertificate: options.getCertificate,
        getPrivateKey: options.getPrivateKey,
        getSignature: options.getSignature
      });
      _clients[url.full] = _state.client;
    }
  }

  /**
   * Opens the request. This method will create the HTTP request to send.
   *
   * @param method the HTTP method (i.e. 'GET').
   * @param url the relative url (the HTTP request path).
   * @param async always true, ignored.
   * @param user always null, ignored.
   * @param password always null, ignored.
   */
  xhr.open = function(method, url, async, user, password) {
    // 1. validate Document if one is associated
    // TODO: not implemented (not used yet)

    // 2. validate method token
    // 3. change method to uppercase if it matches a known
    // method (here we just require it to be uppercase, and
    // we do not allow the standard methods)
    // 4. disallow CONNECT, TRACE, or TRACK with a security error
    switch(method) {
    case 'DELETE':
    case 'GET':
    case 'HEAD':
    case 'OPTIONS':
    case 'PATCH':
    case 'POST':
    case 'PUT':
      // valid method
      break;
    case 'CONNECT':
    case 'TRACE':
    case 'TRACK':
      throw new Error('CONNECT, TRACE and TRACK methods are disallowed');
    default:
      throw new Error('Invalid method: ' + method);;
    }

    // TODO: other validation steps in algorithm are not implemented

    // 19. set send flag to false
    // set response body to null
    // empty list of request headers
    // set request method to given method
    // set request URL
    // set username, password
    // set asychronous flag
    _state.sendFlag = false;
    xhr.responseText = '';
    xhr.responseXML = null;

    // custom: reset status and statusText
    xhr.status = 0;
    xhr.statusText = '';

    // create the HTTP request
    _state.request = http.createRequest({
      method: method,
      path: url
    });

    // 20. set state to OPENED
    xhr.readyState = OPENED;

    // 21. dispatch onreadystatechange
    if(xhr.onreadystatechange) {
       xhr.onreadystatechange();
    }
  };

  /**
   * Adds an HTTP header field to the request.
   *
   * @param header the name of the header field.
   * @param value the value of the header field.
   */
  xhr.setRequestHeader = function(header, value) {
    // 1. if state is not OPENED or send flag is true, raise exception
    if(xhr.readyState != OPENED || _state.sendFlag) {
      throw new Error('XHR not open or sending');
    }

    // TODO: other validation steps in spec aren't implemented

    // set header
    _state.request.setField(header, value);
  };

  /**
   * Sends the request and any associated data.
   *
   * @param data a string or Document object to send, null to send no data.
   */
  xhr.send = function(data) {
    // 1. if state is not OPENED or 2. send flag is true, raise
    // an invalid state exception
    if(xhr.readyState != OPENED || _state.sendFlag) {
      throw new Error('XHR not open or sending');
    }

    // 3. ignore data if method is GET or HEAD
    if(data &&
      _state.request.method !== 'GET' &&
      _state.request.method !== 'HEAD') {
      // handle non-IE case
      if(typeof(XMLSerializer) !== 'undefined') {
        if(data instanceof Document) {
          var xs = new XMLSerializer();
          _state.request.body = xs.serializeToString(data);
        } else {
          _state.request.body = data;
        }
      } else {
        // poorly implemented IE case
        if(typeof(data.xml) !== 'undefined') {
          _state.request.body = data.xml;
        } else {
          _state.request.body = data;
        }
      }
    }

    // 4. release storage mutex (not used)

    // 5. set error flag to false
    _state.errorFlag = false;

    // 6. if asynchronous is true (must be in this implementation)

    // 6.1 set send flag to true
    _state.sendFlag = true;

    // 6.2 dispatch onreadystatechange
    if(xhr.onreadystatechange) {
      xhr.onreadystatechange();
    }

    // create send options
    var options = {};
    options.request = _state.request;
    options.headerReady = function(e) {
      // make cookies available for ease of use/iteration
      xhr.cookies = _state.client.cookies;

      // TODO: update document.cookie with any cookies where the
      // script's domain matches

      // headers received
      xhr.readyState = HEADERS_RECEIVED;
      xhr.status = e.response.code;
      xhr.statusText = e.response.message;
      _state.response = e.response;
      if(xhr.onreadystatechange) {
        xhr.onreadystatechange();
      }
      if(!_state.response.aborted) {
        // now loading body
        xhr.readyState = LOADING;
        if(xhr.onreadystatechange) {
           xhr.onreadystatechange();
        }
      }
    };
    options.bodyReady = function(e) {
      xhr.readyState = DONE;
      var ct = e.response.getField('Content-Type');
      // Note: this null/undefined check is done outside because IE
      // dies otherwise on a "'null' is null" error
      if(ct) {
        if(ct.indexOf('text/xml') === 0 ||
          ct.indexOf('application/xml') === 0 ||
          ct.indexOf('+xml') !== -1) {
          try {
            var doc = new ActiveXObject('MicrosoftXMLDOM');
            doc.async = false;
            doc.loadXML(e.response.body);
            xhr.responseXML = doc;
          } catch(ex) {
            var parser = new DOMParser();
            xhr.responseXML = parser.parseFromString(ex.body, 'text/xml');
          }
        }
      }

      var length = 0;
      if(e.response.body !== null) {
        xhr.responseText = e.response.body;
        length = e.response.body.length;
      }
      // build logging output
      var req = _state.request;
      var output =
        req.method + ' ' + req.path + ' ' +
        xhr.status + ' ' + xhr.statusText + ' ' +
        length + 'B ' +
        (e.request.connectTime + e.request.time + e.response.time) +
        'ms';
      var lFunc;
      if(options.verbose) {
        lFunc = (xhr.status >= 400 && options.logWarningOnError) ?
          _log.warning : _log.verbose;
        lFunc(cat, output,
          e, e.response.body ? '\n' + e.response.body : '\nNo content');
      } else {
        lFunc = (xhr.status >= 400 && options.logWarningOnError) ?
          _log.warning : _log.debug;
        lFunc(cat, output);
      }
      if(xhr.onreadystatechange) {
        xhr.onreadystatechange();
      }
    };
    options.error = function(e) {
      var req = _state.request;
      _log.error(cat, req.method + ' ' + req.path, e);

      // 1. set response body to null
      xhr.responseText = '';
      xhr.responseXML = null;

      // 2. set error flag to true (and reset status)
      _state.errorFlag = true;
      xhr.status = 0;
      xhr.statusText = '';

      // 3. set state to done
      xhr.readyState = DONE;

      // 4. asyc flag is always true, so dispatch onreadystatechange
      if(xhr.onreadystatechange) {
        xhr.onreadystatechange();
      }
    };

    // 7. send request
    _state.client.send(options);
  };

  /**
   * Aborts the request.
   */
  xhr.abort = function() {
    // 1. abort send
    // 2. stop network activity
    _state.request.abort();

    // 3. set response to null
    xhr.responseText = '';
    xhr.responseXML = null;

    // 4. set error flag to true (and reset status)
    _state.errorFlag = true;
    xhr.status = 0;
    xhr.statusText = '';

    // 5. clear user headers
    _state.request = null;
    _state.response = null;

    // 6. if state is DONE or UNSENT, or if OPENED and send flag is false
    if(xhr.readyState === DONE || xhr.readyState === UNSENT ||
     (xhr.readyState === OPENED && !_state.sendFlag)) {
      // 7. set ready state to unsent
      xhr.readyState = UNSENT;
    } else {
      // 6.1 set state to DONE
      xhr.readyState = DONE;

      // 6.2 set send flag to false
      _state.sendFlag = false;

      // 6.3 dispatch onreadystatechange
      if(xhr.onreadystatechange) {
        xhr.onreadystatechange();
      }

      // 7. set state to UNSENT
      xhr.readyState = UNSENT;
    }
  };

  /**
   * Gets all response headers as a string.
   *
   * @return the HTTP-encoded response header fields.
   */
  xhr.getAllResponseHeaders = function() {
    var rval = '';
    if(_state.response !== null) {
      var fields = _state.response.fields;
      $.each(fields, function(name, array) {
        $.each(array, function(i, value) {
          rval += name + ': ' + value + '\r\n';
        });
      });
    }
    return rval;
  };

  /**
   * Gets a single header field value or, if there are multiple
   * fields with the same name, a comma-separated list of header
   * values.
   *
   * @return the header field value(s) or null.
   */
  xhr.getResponseHeader = function(header) {
    var rval = null;
    if(_state.response !== null) {
      if(header in _state.response.fields) {
        rval = _state.response.fields[header];
        if(forge.util.isArray(rval)) {
          rval = rval.join();
        }
      }
    }
    return rval;
  };

  return xhr;
};

// expose public api
forge.xhr = xhrApi;

})(jQuery);
