'use strict';
require('lodash');
const path = require('path');
const koa = require('koa');
const Middles = require('../middleware/');
const extend = require('util')._extend;
let multer  = require('multer');

const app = new koa();
let Bp_modules = require('./bp_modules/');
const querystring = require("querystring");

var request = require('request');
var log4js = require('log4js');
let mongoose = require("mongoose");
const debug = require('debug')('app.js');
// const error = require('debug')('koa-grace-error:views');

var os = require('os');
var ifaces = os.networkInterfaces();
let ip = "0.0.0.0";
function getIp() {
    Object.keys(ifaces).forEach(function (ifname) {
        var alias = 0;

        ifaces[ifname].forEach(function (iface) {
            if ('IPv4' !== iface.family || iface.internal !== false) {
                // skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses
                return;
            }
            if (alias >= 1) {
                // this single interface has multiple ipv4 addresses
                // console.log(ifname + ':' + alias, iface.address);
            } else {
                // this interface has only one ipv4 adress
                console.log(ifname,iface.address)
                if (ifname == "eth0" || ifname == "en0") {
                    ip = iface.address;
                }
                // console.log(ifname, iface.address);
            }
            ++alias;
        });
    });
}
getIp();


function randomString(len) {
  len = len || 32;
  var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';    /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
  var maxPos = chars.length;
  var pwd = '';
  for (var i = 0; i < len; i++) {
    pwd += chars.charAt(Math.floor(Math.random() * maxPos));
  }
  return pwd;
}
// compress(gzip)
app.use(Middles.compress());

// session配置，默认使用内存，不推荐在生产环境使用
// 生产环境推荐配置redis，参考：https://github.com/koa-grace/koa-grace-session
// 目前SESSION的方案还是基于generator的，暂时注释
// app.use(Middles.session(app, config.session));

// body
console.log(">>>>>>>>>>>>>>>>>>")
app.use(Middles.body());

// 配置静态文件路由/Users/yangmei/coding.net/BlackPearl/app/black_pearl_assest
app.use(Middles.static(['/**/black_pearl_assest/**/*', '/**/view/app/**/*','/**/view/views/**/*'], {
  dir: config.path.project,
  maxage: config.site.env == 'production' && 60 * 60 * 1000
}));

// 上传下载功能
app.use(Middles.xload(app, config.xload));
let mogoDbPath = ""
// 获取vhosts
let vhosts = Object.keys(config.vhost).map((item) => {
  let vapp = new koa();

  let appName = config.vhost[item];
  let appPath = path.resolve(config.path.project + '/' + appName);

  // 如果在csrf的module名单里才使用csrf防护功能
  config.csrf.module.indexOf(appName) > -1 && vapp.use(Middles.secure(vapp, {
    throw: true
  }))
  // console.log("======")
  // console.log(appPath)
  // 在开发环境才使用mock数据功能

  config.site.env == 'development' && vapp.use(Middles.mock(vapp, {
    root: appPath + '/mock/',
    prefix: config.mock.prefix + appName
  }))
  mogoDbPath = appPath + '/model/mongo';
  // 如果配置了连接数据库
  config.mongo.api[appName] && vapp.use(Middles.mongo(vapp, {
    root: mogoDbPath,
    connect: config.mongo.api[appName]
  }))

  // 配置api
  vapp.use(Middles.proxy(vapp, config.api, {
    // proxy 配置
    hosts: config.hosts, // 接口域名hosts配置，可以不配置
    allowShowApi: config.site.env !== 'production'
  }, {
      // request 配置
      timeout: config.proxy.timeout // 接口超时时间
    }));

  // 配置模板引擎
  let engine = (typeof config.template === 'string' ? config.template : config.template[appName]);
  vapp.use(Middles.views({
    root: appPath + '/view/views',
    extension: 'html',
    engine: engine || 'swiger',
    locals: {
      constant: config.constant
    },
    cache: config.site.env == 'production' && 'memory'
  }));

  // 配置控制器文件路由
  let prefix = config.router && config.router.prefix && config.router.prefix[appName];
  let suffix = config.router && config.router.suffix && config.router.suffix[appName];
  let errorPath = config.path.default_error && config.path.default_error[appName] || '/error/404';
  vapp.use(Middles.router(vapp, {
    root: appPath + '/controller',
    prefix: prefix,
    suffix: suffix,
    default_path: config.path.default_path[appName],
    default_jump: config.path.default_jump[appName],
    domain: item,
    errorPath: errorPath,
    bpModules: Bp_modules
  }));

  return {
    host: item,
    app: vapp
  }
});

// 注入vhosts路由
app.use(Middles.vhost(vhosts));
/*----------------------------
      自此往下，都是自定义的一些内容          
  ----------------------------
*/
//日志
// log4js.configure({
//   appenders: [
//     { type: 'console' }, //控制台输出
//     {
//       type: 'file', //文件输出
//       filename: 'logs/access.log', 
//       maxLogSize: 1024,
//       backups:3,
//       category: 'normal' 
//     }
//   ]
// });
// var logger = log4js.getLogger('normal');
// logger.setLevel('INFO');

var logger = Bp_modules.log.Logger("app")
logger.info("----------------------------------------------------------------------------------------------!!!!!!!!!!!!")
logger.error("error test================")
console.log('dkkdkdddddddddddddddddddddd')

//自定义 模块的初始化
Bp_modules.route_config.init();


//配置项目路由
// 这里应该是通过数据库来读取具体的配置。然后灌入内存／
// var Projects = require(mogoDbPath+"/projects")

/**
 * 配置外部链接  mongo，初始化数据使用
 */
mongoose.connect(config.mongo.api["blackPearl"]);
var db = mongoose.connection;
var projectModel = mongoose.model("Project");
var urlModel = mongoose.model("Url");
var deviceProjectRoute = mongoose.model("DeviceProjectRoute");
var templateUrlRoute = mongoose.model("TemplateUrlRoute");
var endecodeModel = mongoose.model("Endecode");

//初始化有先后顺序,必须先初始化项目URL路由规则
let init_env = true;
projectModel.find(function () {
}).populate('urls').exec().then(function (pro) {
  debug("项目与URL--路由初始化")
  if(pro.length != 0 ){
    init_env = true;
  }
  Bp_modules.route_config.setProjectRoutes(pro);
}).then(function () {
  if (init_env){
    deviceProjectRoute.find(function (err, items) {
      debug("设备与项目--路由初始化")
      Bp_modules.route_config.setDeviceProjectRoutes(items);
    });
  }
}).then(function () {
  if(init_env){
    urlModel.find().populate("templates").exec(function(err,urls){
      debug("URL与template--路由初始化")
      Bp_modules.route_config.setUrlTemplates(urls);
      // console.log(urls)
    });
    // .populate({ templates: "TemplateUrlRoute", select: "" });
    // console.log(urls);
    // urlModel.find(function (err, items) {
    //   debug("url与模版--路由初始化")
    //   Bp_modules.route_config.setUrlTemplates(items);
    // })
  }
}).then(function(){
  if(init_env){
    endecodeModel.find(function(err, items){
      Bp_modules.endecode.init(items);
      // Bp_modules.route_config.init(items);
    });
  }
});

Bp_modules.datasource.init();

let require_module = {};
require_module["bin"] = require('bankcardinfo');
require_module["xml2json"] = require('xml2json');
//这个是存在内存里面，可以通过调用接口来更新的。





let custom_app = new koa();

custom_app.use(Middles.compress());
custom_app.use(Middles.body());
custom_app.use(async function (ctx, next) {
  //判断Host是否是路由
  // if (ctx.request.header.host == `${ip}:10085`){
  //   return
  // }
  // if(ctx.request)
  //判定设备走那个项目
  console.log(ctx.request.ip)
  //获取当前的项目路由 Object
  if(init_env){
    let project_router = Bp_modules.route_config.getDeviceProjectRoute(ctx);
    let urlRouter = null;
    //获取当前项目下具体的URL路由
    try {
      urlRouter = Bp_modules.route_config.getUrlRoute(ctx,project_router);
      //进行路由匹配，如果不存在，返回404
      if(urlRouter == undefined || urlRouter == false){
        ctx.status = 404;
        ctx.body = { msg: "不存在的MOCK URL" }
        return next
      }
    } catch (error) {
      console.log(error)
    }
    /*
     * 解析当前的 path
     * https://www.npmjs.com/package/path-to-regexp
     * example
     * var re = pathToRegexp('/:foo/:bar')
     * //keys = [{ name: 'foo', prefix: '/', ... }, { name: 'bar', prefix: '/', ... }]
     * re.exec('/test/route')
     * //=> ['/test/route', 'test', 'route']
     */
    let path_parse = urlRouter.re.exec(ctx.path);
    /*
     获取当前 获取当前设备是否有指定模版
     */
    //获取当前URL下面的所有templates
    // let templates = Bp_modules.route_config.getTemplates(urlRouter);
    //遍历模版，查看是否有设备关联,返回false/指定的KEY
    let device_template = Bp_modules.route_config.haveTemplateKeyForDevice(ctx,urlRouter);
    /*
     */
    let script = Bp_modules.route_config.getUrlModuleFromProjectRoute(urlRouter);
    let templateRoute = Bp_modules.route_config.getUrlTemplateRoute(urlRouter);
    // console.log(Bp_modules.endecode);
    try {
      await script(ctx,{
        endecode:  Bp_modules.endecode,
        params: path_parse,
        db: Bp_modules.datasource,
        call_back: Bp_modules.call_back,
        have_device_template:device_template,//true/false
        templageRoute:templateRoute,
        require_module: require_module
      })
      // script.call(ctx,{
      //   params: path_parse,//路径中包含的参数
      //   have_device_template: device_template,
      //   param1: ""//空位
      // });
    } catch (error) {
      console.log(error)
    }
  }
  return
});
custom_app.listen(10085)


// app.bpModules = Bp_modules;
module.exports = app;


/*加密配置，
1、上传文件
2、设定key,
3、执行：runCommand("key",p1,p2,p3,p4)
*/
/* 存储配置


function saveStorage(ctx,key1,value1){
  typeof value1 == string
  typeof value1 == Object JSON.stringify()
  redis.set(key1,)
  ctx.request.ip
}

getStorage()
*/