const glob = require('glob');
const swig = require('swig');

const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');

const memoryCache = require('../utils/memory-cache');
const parseMultiName = require('../utils/parse-multi-name');
const parseRouter = require('./parse-router');
const Stage = require('./stage');

const pageInfo = require('../stages/page-info');
const matchRouter = require('../stages/match-router');
const requestProxy = require('../stages/request-proxy');
const handleInterceptor = require('../stages/handle-interceptor');
const handleRouter = require('../stages/handle-router');
const runTask = require('../stages/run-task');
const getViewPath = require('../stages/get-view-path');
const render = require('../stages/render');
const initHttpRequest = require('../stages/init-http-request');

const pwd = process.cwd();
const defaultRouterDir = `${pwd}/routers`;
const defaultInterceptorDir = `${pwd}/interceptors`;
const defaultViewDir = `${pwd}/views`;

function loadRoutes(dir) {
  const map = {};
  const files = glob.sync(`${dir}/**/*.js`);

  files.forEach(file => {
    const routesPart = require(file); // eslint-disable-line global-require
    Object.assign(map, parseMultiName(routesPart));
  });

  return map;
}

/**
 * 框架定名 route-coc，基于express.js用于简化前端页面直出流程的框架
 * coc 意为 约定优于配置（convention over configuration）
 *
 * @param  {[type]} app  express app对象
 * @param  {[type]} args 配置对象
 * args.routerDir: 路由配置目录
 * args.handleAPI: 预处理api地址
 * @return {[type]}      [description]
 */
module.exports = (app, args = {}) => {
  const defaultStages = [
    pageInfo, matchRouter, initHttpRequest, requestProxy,
    handleInterceptor, handleRouter, runTask, getViewPath, render
  ];
  // mount see more @ http://expressjs.com/en/4x/api.html#path-examples
  const {
    routerDir = defaultRouterDir, // 路由目录
    interceptorDir = defaultInterceptorDir, // 拦截器目录
    viewDir = defaultViewDir,
    viewExclude = ['**/include/**'], // 排除自动渲染模板的目录
    stages = defaultStages,       // 默认stage列表
    mount = '/',                  // 程序挂载路径，类型符合express path examples
    apiDataCache = memoryCache,   // 接口数据缓存方法，默认存储于内存中
    handleAPI = url => url        // api地址预处理方法
  } = args;

  const interceptorMap = loadRoutes(interceptorDir);
  const routerMap = loadRoutes(routerDir);
  const routers = parseRouter(routerMap);
  const interceptors = parseRouter(interceptorMap, interceptor => {
    interceptor.type = 'interceptor';
  });

  // 存储
  app.set('interceptorMap', interceptorMap);
  app.set('interceptors', interceptors);
  app.set('routerMap', routerMap);
  app.set('routers', routers);
  app.set('views', viewDir);
  app.set('viewExclude', viewExclude);
  app.engine('swig', swig.renderFile);
  swig.setDefaults({
    loader: swig.loaders.fs(viewDir)
  });
  // 设置引擎默认后缀
  if (!app.get('view engine')) {
    app.set('view engine', 'swig');
  }
  // 设置接口数据缓存方法
  app.set('apiDataCache', apiDataCache);
  // 设置接口地址处理方法
  app.set('handleAPI', handleAPI);

  Object.keys(args).map(name => {
    app.set(name, args[name]);
    return name;
  });

  // parse application/x-www-form-urlencoded
  app.use(bodyParser.urlencoded({ extended: false }));
  // parse application/json
  app.use(bodyParser.json());
  app.use(cookieParser());
  // nginx代理转发后，要获取正确host需要：
  app.set('trust proxy', 'loopback');
  app.set('query parser', 'extended');

  const stage = new Stage(stages);

  stage.set('app', app);
  stage.set('swig', swig);

  app.use(mount, (req, res, next) => {
    stage.handle(req, res, next);
  });
  app.use((error, req, res, next) => res.status(500).send(`<pre>${error.stack}</pre>`));

  return stage;
};

@@ -1843,24 +1843,34 @@
 ltRouterDir,
+          
  // %E8%B7%AF%E7%94%B1%E7%9B%AE%E5%BD%95%0A   
@@ -1866,16 +1866,16 @@
 // %E8%B7%AF%E7%94%B1%E7%9B%AE%E5%BD%95%0A
-
     inte
@@ -1948,16 +1948,40 @@
 ViewDir,
+               // %E8%A7%86%E5%9B%BE%E6%A8%A1%E6%9D%BF%E7%9B%AE%E5%BD%95
 %0A    vie
@@ -2009,16 +2009,23 @@
 de/**'%5D,
+       
  // %E6%8E%92%E9%99%A4%E8%87%AA%E5%8A%A8
@@ -2031,16 +2031,27 @@
 %E5%8A%A8%E6%B8%B2%E6%9F%93%E6%A8%A1%E6%9D%BF%E7%9A%84%E7%9B%AE%E5%BD%95
+%EF%BC%8C%E9%87%87%E7%94%A8glob%E5%8C%B9%E9%85%8D%E8%A7%84%E5%88%99
 %0A    sta
@@ -2070,16 +2070,26 @@
 tStages,
+          
        /
@@ -2138,15 +2138,32 @@
     
-// %E7%A8%8B%E5%BA%8F%E6%8C%82%E8%BD%BD
+          // %E7%A8%8B%E5%BA%8F%E6%8C%82%E8%BD%BD%E8%B7%AF%E5%BE%84%EF%BC%8C%E9%BB%98%E8%AE%A4%E4%B8%BA%E6%A0%B9
 %E8%B7%AF%E5%BE%84%EF%BC%8C%E7%B1%BB
@@ -2218,16 +2218,26 @@
 ryCache,
+          
    // %E6%8E%A5%E5%8F%A3
@@ -2286,19 +2286,36 @@
         
-// 
+          // router.
 api%E5%9C%B0%E5%9D%80%E9%A2%84%E5%A4%84%E7%90%86
@@ -2316,16 +2316,23 @@
 i%E5%9C%B0%E5%9D%80%E9%A2%84%E5%A4%84%E7%90%86%E6%96%B9%E6%B3%95
+%EF%BC%8C%E9%BB%98%E8%AE%A4%E8%BF%94%E5%9B%9E%E8%87%AA%E8%BA%AB
 %0A  %7D = a

update add some comments