# insight.js

    const _ = require('underscore');
    const AVError = require('./error');
    const { request } = require('./request');

    module.exports = function(AV) {
      /**
       * 包含了使用了 LeanCloud
       *  <a href='/docs/leaninsight_guide.html'>离线数据分析功能</a>的函数。
       * <p><strong><em>
       *   仅在云引擎运行环境下有效。
       * </em></strong></p>
       * @namespace
       */
      AV.Insight = AV.Insight || {};

      _.extend(AV.Insight, /** @lends AV.Insight */ {

        /**
         * 开始一个 Insight 任务。结果里将返回 Job id，你可以拿得到的 id 使用
         * AV.Insight.JobQuery 查询任务状态和结果。
         * @param {Object} jobConfig 任务配置的 JSON 对象，例如：<code><pre>
         *                   { "sql" : "select count(*) as c,gender from _User group by gender",
         *                     "saveAs": {
         *                         "className" : "UserGender",
         *                         "limit": 1
         *                      }
         *                   }
         *                  </pre></code>
         *               sql 指定任务执行的 SQL 语句， saveAs（可选） 指定将结果保存在哪张表里，limit 最大 1000。
         * @param {AuthOptions} [options]
         * @return {Promise} A promise that will be resolved with the result
         * of the function.
         */
        startJob: function(jobConfig, options) {
          if(!jobConfig || !jobConfig.sql) {
            throw new Error('Please provide the sql to run the job.');
          }
          var data = {
            jobConfig: jobConfig,
            appId: AV.applicationId
          };
          return request({
            path: '/bigquery/jobs',
            method: 'POST',
            data: AV._encode(data, null, true),
            authOptions: options,
            signKey: false,
          }).then((resp) => AV._decode(resp).id);
        },

        /**
         * 监听 Insight 任务事件，目前仅支持 end 事件，表示任务完成。
         *  <p><strong><em>
         *     仅在云引擎运行环境下有效。
         *  </em></strong></p>
         * @param {String} event 监听的事件，目前仅支持 'end' ，表示任务完成
         * @param {Function} 监听回调函数，接收 (err, id) 两个参数，err 表示错误信息，
         *                   id 表示任务 id。接下来你可以拿这个 id 使用AV.Insight.JobQuery 查询任务状态和结果。
         *
         */
        on: function(event, cb) {
        }
      });

      /**
       * 创建一个对象，用于查询 Insight 任务状态和结果。
       * @class
       * @param {String} id 任务 id
       * @since 0.5.5
       */
      AV.Insight.JobQuery = function(id, className) {
        if(!id) {
          throw new Error('Please provide the job id.');
        }
        this.id = id;
        this.className = className;
        this._skip = 0;
        this._limit = 100;
      };

      _.extend(AV.Insight.JobQuery.prototype, /** @lends AV.Insight.JobQuery.prototype */ {

        /**
         * Sets the number of results to skip before returning any results.
         * This is useful for pagination.
         * Default is to skip zero results.
         * @param {Number} n the number of results to skip.
         * @return {AV.Query} Returns the query, so you can chain this call.
         */
        skip: function(n) {
          this._skip = n;
          return this;
        },

        /**
         * Sets the limit of the number of results to return. The default limit is
         * 100, with a maximum of 1000 results being returned at a time.
         * @param {Number} n the number of results to limit to.
         * @return {AV.Query} Returns the query, so you can chain this call.
         */
        limit: function(n) {
          this._limit = n;
          return this;
        },

        /**
         * 查询任务状态和结果，任务结果为一个 JSON 对象，包括 status 表示任务状态， totalCount 表示总数，
         * results 数组表示任务结果数组，previewCount 表示可以返回的结果总数，任务的开始和截止时间
         * startTime、endTime 等信息。
         *
         * @param {AuthOptions} [options]
         * @return {Promise} A promise that will be resolved with the result
         * of the function.
         *
         */
        find: function(options) {
          var params = {
            skip: this._skip,
            limit: this._limit
          };

          return request({
            path: `/bigquery/jobs/${this.id}`,
            method: 'GET',
            query: params,
            authOptions: options,
            signKey: false,
          }).then(function(response) {
            if(response.error) {
              return AV.Promise.reject(new AVError(response.code, response.error));
            }
            return AV.Promise.resolve(response);
          });
        }

      });

    };