/**
 * Controller 基类
 * @return {[type]} [description]
 */
var fs = require('fs');
var path = require('path');
var url = require('url');

module.exports = Class(function() {
  'use strict';

  return {
    /**
     * 初始化执行方法
     * @param  {[type]} http [description]
     * @return {[type]}      [description]
     */
    init: function(http) {
      this.http = http;
      this.view = null;
      //将http数据打到模版里
      this.assign('http', this.http);
      //将配置信息打到模版里
      this.assign('config', C());
      //设置变量别名
      this.set = this.assign;
      //success别名
      this.ok = this.success;
      //error别名
      this.fail = this.error;
    },
    /**
     * 获取客户端的ip
     * @return {[type]} [description]
     */
    ip: function() {
      return this.http.ip();
    },
    /**
     * 实例化View类
     * @return {[type]} [description]
     */
    initView: function() {
      if (!this.view) {
        this.view = thinkRequire('View')(this.http);
      }
      return this.view;
    },
    /**
     * 是否是GET请求
     * @return {Boolean} [description]
     */
    isGet: function() {
      return this.http.method === 'GET';
    },
    /**
     * 是否是POST请求
     * @return {Boolean} [description]
     */
    isPost: function() {
      return this.http.method === 'POST';
    },
    /**
     * 是否是特定METHOD请求
     * @param  {[type]}  method [description]
     * @return {Boolean}        [description]
     */
    isMethod: function(method) {
      return this.http.method === method.toUpperCase();
    },
    /**
     * 是否是AJAX请求
     * @return {Boolean} [description]
     */
    isAjax: function(method) {
      //请求类型判断
      if (method && this.http.method !== method.toUpperCase()) {
        return false;
      }
      return this.header('x-requested-with') === 'XMLHttpRequest';
    },
    /**
     * 是否是websocket请求
     * @return {Boolean} [description]
     */
    isWebSocket: function(){
      return !!this.http.websocket;
    },
    /**
     * 是否是命令行模式
     * @return {Boolean} [description]
     */
    isCli: function(){
      return APP_MODE === 'cli';
    },
    /**
     * 是否是jsonp接口
     * @return {Boolean} [description]
     */
    isJsonp: function(name){
      name = name || C('url_callback_name');
      return !!this.get(name);
    },
    /**
     * token功能
     * @return {[type]} [description]
     */
    token: function(token){
      var tokenName = C('token_name');
      var self = this;
      if (token) {
        return this.session(tokenName).then(function(value){
          return value === token;
        })
      }else{
        return this.session(tokenName).then(function(token){
          if (token) {
            return token;
          }
          token = thinkRequire('Session').uid(32);
          return self.session(tokenName, token).then(function(){
            return token;
          })
        })
      }
    },
    /**
     * 获取QUERY参数
     * @param  {[type]} name [description]
     * @return {[type]}      [description]
     */
    get: function(name) {
      if (name === undefined) {
        return this.http.get;
      }
      return this.http.get[name] || '';
    },
    /**
     * 获取POST参数
     * @param  {[type]} name [description]
     * @return {[type]}      [description]
     */
    post: function(name) {
      var http = this.http;
      return name ? (http.post[name] || '') : http.post;
    },
    /**
     * 获取参数
     * @param  {[type]} name [description]
     * @return {[type]}      [description]
     */
    param: function(name) {
      if (name === undefined) {
        var post = this.post();
        return !isEmpty(post) ? post : this.get();
      }
      return this.post(name) || this.get(name);
    },
    /**
     * 获取上传的文件
     * @param  {[type]} name [description]
     * @return {[type]}      [description]
     */
    file: function(name) {
      var http = this.http;
      return name ? (http.file[name] || {}) : http.file;
    },
    /**
     * header操作
     * @param  {[type]} name  [description]
     * @param  {[type]} value [description]
     * @return {[type]}       [description]
     */
    header: function(name, value) {
      if (name === undefined) {
        return this.http.headers;
      }else if (isObject(name)) {
        for (var key in name) {
          this.header(key, name[key]);
        }
        return this;
      }else if (value !== undefined) {
        if (name === 'Content-Type') {
          return this.type(value);
        }
        this.http.setHeader(name, value);
        return this;
      }else{
        return this.http.getHeader(name);
      }
    },
    /**
     * 获取userAgent
     * @return {[type]} [description]
     */
    userAgent: function(){
      return this.http.headers['user-agent'] || '';
    },
    /**
     * 获取referrer
     * @return {[type]} [description]
     */
    referer: function(host){
      var referer = this.http.headers.referer || this.http.headers.referrer || '';
      if (!referer || !host) {
        return referer;
      }
      var info = url.parse(referer);
      return info.hostname;
    },
    /**
     * cookie操作
     * @param  {[type]} name    [description]
     * @param  {[type]} value   [description]
     * @param  {[type]} options [description]
     * @return {[type]}         [description]
     */
    cookie: function(name, value, options) {
      if (value !== undefined) {
        this.http.setCookie(name, value, options);
        return this;
      }
      return name === undefined ? this.http.cookie : (this.http.cookie[name] || '');
    },
    /**
     * session
     * 如果是get操作，则返回一个promise
     * @param  {[type]} name  [description]
     * @param  {[type]} value [description]
     * @return {[type]}       [description]
     */
    session: function(name, value) {
      thinkRequire('Session').start(this.http);
      var instance = this.http.session;
      if (name === undefined) {
        return instance.rm();
      }
      if (value !== undefined) {
        return instance.set(name, value);
      }
      return instance.get(name);
    },
    /**
     * 跳转，返回一个pendding promise阻止后面继续执行
     * @param  {[type]} url  [description]
     * @param  {[type]} code [description]
     * @return {[type]}      [description]
     */
    redirect: function(url, code) {
      this.http.redirect(url, code);
      return getDefer().promise;
    },
    /**
     * 赋值变量到模版
     * @param  {[type]} name  [description]
     * @param  {[type]} value [description]
     * @return {[type]}       [description]
     */
    assign: function(name, value) {
      if (arguments.length <= 1) {
        return this.initView().assign(name);
      }
      return this.initView().assign(name, value);
    },
    /**
     * 获取解析后的模版内容
     * @param  {[type]} templateFile [description]
     * @param  {[type]} content      [description]
     * @return {[type]}              [description]
     */
    fetch: function(templateFile) {
      return this.initView().fetch(templateFile);
    },
    /**
     * 输出模版内容
     * @param  {[type]} templateFile [description]
     * @param  {[type]} charset      [description]
     * @param  {[type]} contentType  [description]
     * @param  {[type]} content      [description]
     * @return {[type]}              [description]
     */
    display: function(templateFile, charset, contentType) {
      return this.initView().display(templateFile, charset, contentType);
    },
    /**
     * 调用另一个controll里的aciton
     * 可以跨分组
     * A('Admin/Test/index')
     * @param  {[type]} action [description]
     * @return {[type]}        [description]
     */
    action: function(action, data) {
      //自动补group
      action = action.replace(/\//g, ':');
      if (action.split(':').length === 2) {
        action = this.http.group + ':' + action;
      }
      return A(action, this.http, data);
    },
    /**
     * jsonp格式输出
     * @param  {[type]} data  [description]
     * @param  {[type]} jsonp [description]
     * @return {[type]}       [description]
     */
    jsonp: function(data) {
      this.type(C('json_content_type'));
      var callback = this.get(C('url_callback_name'));
      //过滤callback值里的非法字符
      callback = callback.replace(/[^\w\.]/g, '');
      if (callback) {
        data = callback + '(' + (data !== undefined ? JSON.stringify(data) : '') + ')';
        this.end(data);
      } else {
        this.end(data);
      }
    },
    /**
     * json格式输出
     * @param  {[type]} data [description]
     * @return {[type]}      [description]
     */
    json: function(data){
      this.type(C('json_content_type'));
      return this.end(data);
    },
    /**
     * 设置http响应状态码
     * @param  {[type]} status [description]
     * @return {[type]}        [description]
     */
    status: function(status) {
      var res = this.http.res;
      if (!res.headersSent) {
        res.statusCode = status || 404;
      }
      return this;
    },
    /**
     * 阻止访问
     * @param  {[type]} status [description]
     * @return {[type]}        [description]
     */
    deny: function(status){
      var res = this.http.res;
      if (!res.headersSent) {
        res.statusCode = status || 403;
        this.http.end();
      }
      return getDefer().promise;
    },
    /**
     * 输出内容
     * 自动JSON.stringify
     * 自定将数字等转化为字符串
     * @param  {[type]} obj [description]
     * @return {[type]}     [description]
     */
    echo: function(obj, encoding) {
      //自动发送Content-Type的header
      if (C('auto_send_content_type')) {
        this.type(C('tpl_content_type'));
      }
      return this.http.echo(obj, encoding);
    },
    /**
     * 结束输出，输出完成时一定要调用这个方法
     * @param  {[type]} obj [description]
     * @return {[type]}     [description]
     */
    end: function(obj, encoding) {
      if (obj !== undefined) {
        var self = this;
        return this.echo(obj, encoding).then(function(){
          self.http.end();
        });
      }
      this.http.end();
    },
    /**
     * 发送Content-Type
     * @param  {[type]} type [description]
     * @return {[type]}      [description]
     */
    type: function(ext){
      if (this.http.cthIsSend || !ext) {
        return;
      }
      if (ext.indexOf('/') === -1) {
        ext = require('mime').lookup(ext);
      }
      if (ext.toLowerCase().indexOf('charset=') === -1) {
        ext += '; charset=' + C('encoding');
      }
      //Content-Type Header has been Send
      this.http.cthIsSend = true;
      this.http.setHeader('Content-Type', ext);
      return this;
    },
    /**
     * 下载文件
     * @return Promise [description]
     */
    download: function(file, contentType, filename) {
      if (isString(contentType) && contentType.indexOf('.') > -1) {
        filename = contentType;
        contentType = '';
      }
      if (!contentType || contentType.indexOf('/') === -1) {
        contentType = require('mime').lookup(contentType || file);
      }
      var http = this.http;
      var fileStream = fs.createReadStream(file);
      var deferred = getDefer();
      this.type(contentType);
      http.setHeader('Content-Disposition', 'attachment; filename="' + (filename || path.basename(file)) + '"');
      fileStream.pipe(http.res);
      fileStream.on('end', function() {
        http.end();
        deferred.resolve();
      });
      return deferred.promise;
    },
    /**
     * 正常json数据输出
     * @param  {[type]} data [description]
     * @return {[type]}      [description]
     */
    success: function(data){
      var obj = getObject([C('error_no_key'), C('error_msg_key')], [0, '']);
      if (data !== undefined) {
        obj.data = data;
      }
      this.type(C('json_content_type'));
      this.end(obj);
      return getDefer().promise;
    },
    /**
     * 异常json数据数据
     * @param  {[type]} errno  [description]
     * @param  {[type]} errmsg [description]
     * @param  {[type]} extra  [description]
     * @return {[type]}        [description]
     */
    error: function(errno, errmsg, data){
      var obj;
      if (isObject(errno)) {
        data = errmsg;
        obj = extend({}, errno);
      }else{
        if (!isNumber(errno)) {
          data = errmsg;
          errmsg = errno;
          errno = C('error_no_default_value');
        }
        obj = getObject([C('error_no_key'), C('error_msg_key')], [errno, errmsg || 'error']);
      }
      if (data !== undefined) {
        obj.data = data;
      }
      this.type(C('json_content_type'));
      this.end(obj);
      return getDefer().promise;
    },
    /**
     * 关闭数据库连接
     * @return {[type]} [description]
     */
    closeDb: function(){
      thinkRequire('Model').close();
    },
    /**
     * 发送执行时间
     * @param  {[type]} name [description]
     * @return {[type]}      [description]
     */
    sendTime: function(name){
      return this.http.sendTime(name);
    },
    /**
     * 对数据进行过滤
     * @param  {[type]} data [description]
     * @param  {[type]} type [description]
     * @return {[type]}      [description]
     */
    filter: function() {
      var filter = thinkRequire('Filter').filter;
      return filter.apply(null, arguments);
    },
    /**
     * 校验一个值是否合法
     * @param  {[type]} data      [description]
     * @param  {[type]} validType [description]
     * @return {[type]}           [description]
     */
    valid: function(data, validType) {
      //单个值检测，只返回是否正常
      if (validType !== undefined) {
        data = [{
          value: data,
          valid: validType
        }];
        var result = thinkRequire('Valid')(data);
        return isEmpty(result);
      }
      return thinkRequire('Valid')(data);
    }
  };
});