text: var urlParse        = require('url').parse;
  var ClientConstants = require('./protocol/constants/client');
  var Charsets        = require('./protocol/constants/charsets');
  var SSLProfiles     = null;
  
  module.exports = ConnectionConfig;
  function ConnectionConfig(options) {
    if (typeof options === 'string') {
      options = ConnectionConfig.parseUrl(options);
    }
  
    this.host               = options.host || 'localhost';
    this.port               = options.port || 3306;
    this.localAddress       = options.localAddress;
    this.socketPath         = options.socketPath;
    this.user               = options.user || undefined;
    this.password           = options.password || undefined;
    this.database           = options.database;
    this.connectTimeout     = (options.connectTimeout === undefined)
      ? (10 * 1000)
      : options.connectTimeout;
    this.insecureAuth       = options.insecureAuth || false;
    this.supportBigNumbers  = options.supportBigNumbers || false;
    this.bigNumberStrings   = options.bigNumberStrings || false;
    this.compress           = options.compress || false;
    this.dateStrings        = options.dateStrings || false;
    this.debug              = options.debug;
    this.trace              = options.trace !== false;
    this.stringifyObjects   = options.stringifyObjects || false;
    this.timezone           = options.timezone || 'local';
    this.flags              = options.flags || '';
    this.queryFormat        = options.queryFormat;
    this.pool               = options.pool || undefined;
    this.ssl                = (typeof options.ssl === 'string')
      ? ConnectionConfig.getSSLProfile(options.ssl)
      : (options.ssl || false);
    this.localInfile        = (options.localInfile === undefined)
      ? true
      : options.localInfile;
    this.multipleStatements = options.multipleStatements || false;
    this.typeCast           = (options.typeCast === undefined)
      ? true
      : options.typeCast;
    this.enableKeepAlive    = options.enableKeepAlive || false;
    this.keepAliveInitialDelay = options.keepAliveInitialDelay || 0;
  
    if (this.timezone[0] === ' ') {
      // "+" is a url encoded char for space so it
      // gets translated to space when giving a
      // connection string..
      this.timezone = '+' + this.timezone.substr(1);
    }
  
    if (this.ssl) {
      // Default rejectUnauthorized to true
      this.ssl.rejectUnauthorized = this.ssl.rejectUnauthorized !== false;
    }
  
    this.maxPacketSize = 0;
    this.charsetNumber = (options.charset)
      ? ConnectionConfig.getCharsetNumber(options.charset)
      : options.charsetNumber || Charsets.UTF8_GENERAL_CI;
  
    // Set the client flags
    var defaultFlags = ConnectionConfig.getDefaultFlags(options);
    this.clientFlags = ConnectionConfig.mergeFlags(defaultFlags, options.flags);
  
    this.secureAuth = options.secureAuth !== undefined ? options.secureAuth : true;
  }
  
  ConnectionConfig.mergeFlags = function mergeFlags(defaultFlags, userFlags) {
    var allFlags = ConnectionConfig.parseFlagList(defaultFlags);
    var newFlags = ConnectionConfig.parseFlagList(userFlags);
  
    // Merge the new flags
    for (var flag in newFlags) {
      if (allFlags[flag] !== false) {
        allFlags[flag] = newFlags[flag];
      }
    }
  
    // Build flags
    var flags = 0x0;
    for (var flag in allFlags) {
      if (allFlags[flag]) {
        // TODO: Throw here on some future release
        flags |= ClientConstants['CLIENT_' + flag] || 0x0;
      }
    }
  
    return flags;
  };
  
  ConnectionConfig.getCharsetNumber = function getCharsetNumber(charset) {
    var num = Charsets[charset.toUpperCase()];
  
    if (num === undefined) {
      throw new TypeError('Unknown charset \'' + charset + '\'');
    }
  
    return num;
  };
  
  ConnectionConfig.getDefaultFlags = function getDefaultFlags(options) {
    var defaultFlags = [
      '-CONNECT_ATTRS',     // Does *NOT* send connection attributes in Protocol::HandshakeResponse41
      '+CONNECT_WITH_DB',   // One can specify db on connect in Handshake Response Packet
      '+FOUND_ROWS',        // Send found rows instead of affected rows
      '+IGNORE_SIGPIPE',    // Don't issue SIGPIPE if network failures
      '+IGNORE_SPACE',      // Let the parser ignore spaces before '('
      '+LOCAL_FILES',       // Can use LOAD DATA LOCAL
      '+LONG_FLAG',         // Longer flags in Protocol::ColumnDefinition320
      '+LONG_PASSWORD',     // Use the improved version of Old Password Authentication
      '+MULTI_RESULTS',     // Can handle multiple resultsets for COM_QUERY
      '+ODBC',              // Special handling of ODBC behaviour
      '+PLUGIN_AUTH',       // Supports auth plugins
      '+PROTOCOL_41',       // Uses the 4.1 protocol
      '+PS_MULTI_RESULTS',  // Can handle multiple resultsets for COM_STMT_EXECUTE
      '+RESERVED',          // Unused
      '+SECURE_CONNECTION', // Supports Authentication::Native41
      '+TRANSACTIONS'       // Expects status flags
    ];
  
    if (options && options.localInfile !== undefined && !options.localInfile) {
      // Disable LOCAL modifier for LOAD DATA INFILE
      defaultFlags.push('-LOCAL_FILES');
    }
  
    if (options && options.multipleStatements) {
      // May send multiple statements per COM_QUERY and COM_STMT_PREPARE
      defaultFlags.push('+MULTI_STATEMENTS');
    }
  
    return defaultFlags;
  };
  
  ConnectionConfig.getSSLProfile = function getSSLProfile(name) {
    if (!SSLProfiles) {
      SSLProfiles = require('./protocol/constants/ssl_profiles');
    }
  
    var ssl = SSLProfiles[name];
  
    if (ssl === undefined) {
      throw new TypeError('Unknown SSL profile \'' + name + '\'');
    }
  
    return ssl;
  };
  
  ConnectionConfig.parseFlagList = function parseFlagList(flagList) {
    var allFlags = Object.create(null);
  
    if (!flagList) {
      return allFlags;
    }
  
    var flags = !Array.isArray(flagList)
      ? String(flagList || '').toUpperCase().split(/\s*,+\s*/)
      : flagList;
  
    for (var i = 0; i < flags.length; i++) {
      var flag   = flags[i];
      var offset = 1;
      var state  = flag[0];
  
      if (state === undefined) {
        // TODO: throw here on some future release
        continue;
      }
  
      if (state !== '-' && state !== '+') {
        offset = 0;
        state  = '+';
      }
  
      allFlags[flag.substr(offset)] = state === '+';
    }
  
    return allFlags;
  };
  
  ConnectionConfig.parseUrl = function(url) {
    url = urlParse(url, true);
  
    var options = {
      host     : url.hostname,
      port     : url.port,
      database : url.pathname.substr(1)
    };
  
    if (url.auth) {
      var auth = url.auth.split(':');
      options.user     = auth.shift();
      options.password = auth.join(':');
    }
  
    if (url.query) {
      for (var key in url.query) {
        var value = url.query[key];
  
        try {
          // Try to parse this as a JSON expression first
          options[key] = JSON.parse(value);
        } catch (err) {
          // Otherwise assume it is a plain string
          options[key] = value;
        }
      }
    }
  
    return options;
  };
  