text: /**
   * 框架核心
   * @authors yutent (yutent@doui.cc)
   * @date    2015-11-25 18:06:14
   *
   */
  'use strict'
  
  require('es.shim') // 加载拓展方法
  var init = require('./lib/reg-init')
  
  var log = console.log
  var http = require('http')
  var path = require('path')
  var Request = require('http.request')
  var Response = require('http.response')
  var routerWare = require('./lib/middleware/router')
  var cookieWare = require('./lib/middleware/cookie')
  var sessionWare = require('./lib/middleware/session')
  var credentialsWare = require('./lib/middleware/credentials')
  
  function hideProperty(host, name, value) {
    Object.defineProperty(host, name, {
      value: value,
      writable: true,
      enumerable: false,
      configurable: true
    })
  }
  
  class Five {
    constructor() {
      hideProperty(this, '__FIVE__', Object.assign({}, init))
      hideProperty(this, '__MODULES__', { __error__: null })
      hideProperty(this, '__MIDDLEWARE__', [])
      hideProperty(this, '__INSTANCE__', {})
  
      global.libs = {
        Smarty: require('smartyx'), //模板引擎
        Log: require('./lib/module/log'), //基础日志记录工具
        Email: require('./lib/module/sendmail'), //加载email发送类
        Mysql: require('mysqli'), //加载mysql操作类
        Ioredis: require('ioredis')
      }
      global.Util = {
        sec: require('crypto.js'),
        path: require('path'),
        url: require('url'),
        fs: require('iofs'),
        child: require('child_process')
      }
      global.Controller = require('./lib/controller')
    }
  
    __init__() {
      var { domain, website, session } = this.__FIVE__
      domain = domain || website
      session.domain = session.domain || domain
      this.set({ domain, session })
  
      // 这里只创建session的存储器, 而初始化操作在中间件中进行
      if (session.type === 'redis') {
        hideProperty(
          this,
          '__SESSION_STORE__',
          new libs.Ioredis({
            host: session.db.host || '127.0.0.1',
            port: session.db.port || 6379,
            db: session.db.db || 0
          })
        )
      } else {
        hideProperty(this, '__SESSION_STORE__', {})
      }
  
      // 将session和cookie的中间件提到最前
      // 以便用户自定义的中间件可以直接操作session和cookie
      this.__MIDDLEWARE__.unshift(sessionWare)
      this.__MIDDLEWARE__.unshift(cookieWare)
      this.__MIDDLEWARE__.unshift(credentialsWare)
  
      this.use(routerWare)
    }
  
    /*------------------------------------------------------------------------*/
  
    // 注册属性到全局Five对象
    set(obj) {
      for (let i in obj) {
        if (typeof obj[i] === 'object' && !Array.isArray(obj[i])) {
          if (!this.__FIVE__[i]) {
            this.__FIVE__[i] = obj[i]
          } else {
            try {
              Object.assign(this.__FIVE__[i], obj[i])
            } catch (err) {
              log(err)
            }
          }
        } else {
          this.__FIVE__[i] = obj[i]
        }
      }
      return this
    }
  
    // 获取全局配置
    get(key) {
      try {
        return new Function('o', `return o.${key}`)(this.__FIVE__)
      } catch (err) {
        return
      }
    }
  
    // 加载中间件/缓存模块
    // 与别的中间件用法有些不一样, 回调的传入参数中的req和res,
    // 并非原生的request对象和response对象,
    // 而是框架内部封装过的,可通过origin属性访问原生的对象
    use(key, fn) {
      if (arguments.length === 1) {
        if (typeof key !== 'function') {
          throw TypeError('argument 1 must be a callback')
        }
        this.__MIDDLEWARE__.push(key)
      } else {
        if (typeof key !== 'string') {
          return
        }
        libs[key] = fn
      }
    }
    // 预加载应用
    preload(dir) {
      var list = Util.fs.ls(dir)
  
      if (list) {
        list.forEach(file => {
          var { name } = path.parse(file)
          if (name.startsWith('.')) {
            return
          }
          try {
            this.__MODULES__[name] = require(file)
          } catch (err) {
            this.__MODULES__.__error__ = err
          }
        })
      }
  
      return this
    }
  
    // 注册实例化对象到实例池中
    // 与use方法不同的是, 这个会在server创建之前就已经执行
    ins(name, fn) {
      var _this = this
      if (arguments.length === 1) {
        return this.__INSTANCE__[name]
      }
      if (typeof fn === 'function') {
        fn.call(this, this.__FIVE__, function next(instance) {
          if (instance) {
            _this.__INSTANCE__[name] = instance
          }
        })
      }
    }
  
    // 启动http服务
    listen(port) {
      var _this = this
  
      this.__init__()
  
      var server = http.createServer(function(req, res) {
        var response = new Response(req, res)
        var request = new Request(req, res)
  
        response.set('X-Powered-By', 'Five.js')
  
        var middleware = _this.__MIDDLEWARE__.concat()
        var fn = middleware.shift()
        if (fn) {
          ;(async function next() {
            await fn.call(_this, request, response, function() {
              fn = middleware.shift()
              if (fn) {
                next()
              }
            })
          })()
        }
      })
  
      server.listen(port || this.get('port'))
  
      return server
    }
  }
  
  module.exports = Five
  