/*!
 * vhost
 * Copyright(c) 2014 Jonathan Ong
 * Copyright(c) 2014 Douglas Christopher Wilson
 * MIT Licensed
 */

'use strict'

/**
 * Create a vhost middleware.
 *
 * @param {string|RegExp} hostname
 * @param {function} handle
 * @return {Function}
 * @public
 */

module.exports = function vhost(hostname, handle) {
  if (!hostname) {
    throw new TypeError('argument hostname is required')
  }

  if (!handle) {
    throw new TypeError('argument handle is required')
  }

  if (typeof handle !== 'function') {
    throw new TypeError('argument handle must be a function')
  }

  // create regular expression for hostname
  var regexp = hostregexp(hostname)

  return function vhost(req, res, next){
    var vhostdata = vhostof(req, regexp)

    if (!vhostdata) {
      return next()
    }

    // populate
    req.vhost = vhostdata

    // handle
    handle(req, res, next)
  };
};

/**
 * Get hostname of request.
 *
 * @param (object} req
 * @return {string}
 * @private
 */

function hostnameof(req){
  var host = req.headers.host

  if (!host) {
    return
  }

  var offset = host[0] === '['
    ? host.indexOf(']') + 1
    : 0
  var index = host.indexOf(':', offset)

  return index !== -1
    ? host.substring(0, index)
    : host
}

/**
 * Determine if object is RegExp.
 *
 * @param (object} val
 * @return {boolean}
 * @private
 */

function isregexp(val){
  return Object.prototype.toString.call(val) === '[object RegExp]'
}

/**
 * Generate RegExp for given hostname value.
 *
 * @param (string|RegExp} val
 * @private
 */

function hostregexp(val){
  var source = !isregexp(val)
    ? String(val).replace(/([.+?^=!:${}()|\[\]\/\\])/g, '\\$1').replace(/\*/g, '([^\.]+)')
    : val.source

  // force leading anchor matching
  if (source[0] !== '^') {
    source = '^' + source
  }

  // force trailing anchor matching
  source = source.replace(/(\\*)(.)$/, function(s, b, c){
    return c !== '$' || b.length % 2 === 1
      ? s + '$'
      : s
  })

  return new RegExp(source, 'i')
}

/**
 * Get the vhost data of the request for RegExp
 *
 * @param (object} req
 * @param (RegExp} regexp
 * @return {object}
 * @private
 */

function vhostof(req, regexp){
  var host = req.headers.host
  var hostname = hostnameof(req)

  if (!hostname) {
    return
  }

  var match = regexp.exec(hostname)

  if (!match) {
    return
  }

  var obj = Object.create(null)

  obj.host = host
  obj.hostname = hostname
  obj.length = match.length - 1

  for (var i = 1; i < match.length; i++) {
    obj[i - 1] = match[i]
  }

  return obj
}
