var JELON = window.JELON || {};
;(function (JL) {
  var constants = {
    ACCESS_TOKEN_KEY: 'xups-github-comments-token', // access_token key
    USER_INFO_KEY: 'xups-github-user-info',         // 登录用户信息 key
    PER_PAGE: 10,                                    // 每页的评论数
    API_HOST: 'https://api.github.com'
  };
  var queryUrl = function (key, url, uncode) {
    url = url || location.href;
    var reg = new RegExp('(\\?|&|#|&amp;)' + key + '=([^?&#]*)');
    var result = url.match(reg);
    if (uncode) {
      return result ? result[2] : '';
    }
    return result ? decodeURIComponent(result[2]) : '';
  };
  var $ = JL.$ || function(str) {
    return /^(\[object HTML)[a-zA-Z]*(Element\])$/.test(Object.prototype.toString.call(str)) ? str : document.getElementById(str);
  };
  var addClass = function (elem, className) {
    if (!elem) return;
    var classNames;
    var setClass;
    var i, l, cl;
    if (elem instanceof Array) {
      for (i = 0, l = elem.length; i < l; i++) {
        elem[i] = arguments.callee.call(this, elem[i], className);
      }
    } else if (typeof elem.item === 'function') {
      var result = [];
      for (i = 0, l = elem.length; i < l; i++) {
        result.push(arguments.callee.call(this, elem.item(i), className));
      }
      elem = result;
    } else {
      elem = $(elem);
      if (!elem) return;
      if (className && typeof className === 'string') {
        classNames = className.split(/\s+/);
        if (elem.nodeType === 1) {
          if (!elem.className && classNames.length === 1) {
            elem.className = className;
          } else {
            setClass = ' ' + elem.className + ' ';
            for (i = 0, cl = classNames.length; i < cl; i++) {
              if (setClass.indexOf(' ' + classNames[i] + ' ') < 0) {
                setClass += classNames[i] + ' ';
              }
            }
            elem.className = setClass.trim();
          }
        }
      }
    }
    return elem;
  };
  var removeClass = function (elem, className) {
    if (!elem) return;
    var classNames, i, l, c, cl;
    if (elem instanceof Array) {
      for (i = 0, l = elem.length; i < l; i++) {
        elem[i] = arguments.callee.call(this, elem[i], className);
      }
    } else if (typeof elem.item === 'function') {
      var result = [];
      for (i = 0, l = elem.length; i < l; i++) {
        result.push(arguments.callee.call(this, elem.item(i), className));
      }
      elem = result;
    } else {
      elem = $(elem);
      if (!elem) return;
      if ((className && typeof className === 'string') || className === undefined) {
        classNames = (className || '').split(/\s+/);
        if (elem.nodeType === 1 && elem.className) {
          if (className) {
            className = (' ' + elem.className + ' ').replace(/[\n\t\r]/g, ' ');
            for (c = 0, cl = classNames.length; c < cl; c++) {
              className = className.replace(' ' + classNames[c] + ' ', ' ');
            }
            elem.className = className.trim();
          } else {
            elem.className = '';
          }
        }
      }
    }
    return elem;
  };
  /**
   * 格式化日期文本，如 yyyy-MM-dd hh:mm:ss
   */
  var formatDate = function (format, date) {
    if (!date) return '';
    if (typeof date == 'number') date = new Date(date * 1000);
    var o = {
      'M+': date.getMonth() + 1,
      'd+': date.getDate(),
      'h+': date.getHours(),
      'm+': date.getMinutes(),
      's+': date.getSeconds(),
      'q+': Math.floor((date.getMonth() + 3) / 3),
      'S': date.getMilliseconds(),
      'w': '日一二三四五六'.charAt(date.getDay())
    };
    format = format.replace(/y{4}/, date.getFullYear()).replace(/y{2}/, date.getFullYear().toString().substring(2));
    for (var k in o) {
      var reg = new RegExp(k);
      format = format.replace(reg, match);
    }
    function match(m) {
      return m.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length);
    }
    return format;
  };
  /**
   * 分享到社交平台
   * @param {String} type 
   */
  var share = function(type) {
    if(!type) return;
    switch (type) {
      case 'weibo' : //微博
        window.open('http://service.weibo.com/share/share.php?url=' + 
          encodeURIComponent(location.href) + '&title=' + document.title + '&language=zh_cn');
        break;
      case 'qqzone' : //QQ空间
        window.open('http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=' + 
          encodeURIComponent(location.href) + '&title=' + document.title);
        break;
      case 'qq' : //QQ
        window.open('http://connect.qq.com/widget/shareqq/index.html?url=' + 
          encodeURIComponent(location.href) + '&desc=Silence个人博客&title=' + 
          document.title + '&callback=' + encodeURIComponent(location.href));
        break;
      case 'douban' : //豆瓣
        window.open('http://shuo.douban.com/!service/share?href=' + 
          encodeURIComponent(location.href) + '&name=' + document.title + '&text=' + document.title);
        break;
      default : console.warn('未知的分享类型', type)
    }
  }
  /**
   * 过滤字符串中的style link script标签, 防止注入
   * @param {String} str 需要处理的字符串
   */
  var htmlFilter = function (str) {
    if (typeof str !== 'string') return;
    str = str.replace(/(<style.*?<\/style>)/g, '')
        .replace(/(<link.*\s+href=(?:"[^"]*"|'[^']*')[^<]*>)/g, '')
        .replace(/<script.*?>.*?<\/script>/g, '');
    return str;
  };

  /**
   * 封装ajax函数
   * @param {String}   opt.method        连接的方式，包括POST和GET两种方式
   * @param {String}   opt.url           发送请求的url
   * @param {Boolean}  opt.async         是否为异步请求，true为异步的，false为同步的
   * @param {Object}   opt.data          发送的参数，格式为对象类型
   * @param {Function} opt.success       发送并接收成功调用的回调函数
   * @param {Function} opt.fail          失败回调
   */
  var ajax = function (opt) {
    opt = opt || {};
    opt.method = opt.method.toUpperCase() || 'POST';
    opt.url = opt.url || '';
    opt.async = opt.async || true;
    opt.data = opt.data || null;
    opt.success = opt.success || function () {};
    var xhr = null;
    if (window.XMLHttpRequest) {
      xhr = new XMLHttpRequest();
    } else {
      xhr = new ActiveXObject('Microsoft.XMLHTTP');
    }
    var params = [];
    var token = window.localStorage.getItem(constants.ACCESS_TOKEN_KEY);

    for (var key in opt.data) {
      params.push(key + '=' + opt.data[key]);
    }
    var postData = params.join('&');
    if (opt.method.toUpperCase() === 'POST') {
      xhr.open(opt.method, opt.url, opt.async);
      if (window.JSON) {
        postData = JSON.stringify(opt.data);
        xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8');
      } else {
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
      }
      if (opt.headers && opt.headers['Accept']) {
        xhr.setRequestHeader('Accept', opt.headers['Accept']);
      } else {
        xhr.setRequestHeader('Accept', 'application/vnd.github.squirrel-girl-preview, application/vnd.github.html+json');
      }
      // 登录校验
      if (token) {
        xhr.setRequestHeader('Authorization', 'token ' + token);
      }
      xhr.send(postData);
    } else if (opt.method.toUpperCase() === 'GET') {
      xhr.open(opt.method, opt.url + '?' + postData, opt.async);
      xhr.setRequestHeader('Accept', 'application/vnd.github.squirrel-girl-preview, application/vnd.github.html+json');
      // 登录校验
      if (token) {
        xhr.setRequestHeader('Authorization', 'token ' + token);
      }
      xhr.send(null);
    }

    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status >= 200 && xhr.status < 300) {
          opt.success && opt.success(xhr.responseText);
        } else {
          opt.fail && opt.fail(xhr.status)
        }
      }
    };
    xhr.onerror = function () {
      opt.fail && opt.fail({ message: '请求错误！' });
    };
  };
  JL.issueComments = 0;
  JL.issueNumber = 0;
  JL.Utils = {
    ajax: ajax,
    queryUrl: queryUrl,
    addClass: addClass,
    removeClass: removeClass,
    formatDate: formatDate,
    share: share
  };
  JL.Renders = {
    box: {
      tpl: [
        '<section class="box" id="JELON__commentBox">',
          '<div class="com-avatar"><img id="loginAvatar" src="/img/loading.gif" alt="avatar"></div>',
          '<div class="com-text">',
            '<div class="main">',
              '<textarea class="text-area-edited show" id="JELON__editBox" placeholder="欢迎评论！"></textarea>',
              '<div class="text-area-preview" id="JELON__previewBox"></div>',
            '</div>',
            '<div class="switch">',
              '<div class="switch-item on" id="JELON__editSwitcher" onclick="JELON.Actions.editPreviewSwitch(\'edit\')">编辑</div>',
              '<div class="switch-item" id="JELON__previewSwitcher" onclick="JELON.Actions.editPreviewSwitch(\'preview\')">预览</div>',
            '</div>',
            '<div class="button" onclick="JELON.Actions.postComment()">提交</div>',
          '</div>',
        '</section>'
      ].join(''),
      update: function () {
        var userInfo = localStorage.getItem(constants.USER_INFO_KEY);
        if (userInfo) {
          userInfo = JSON.parse(userInfo);
        } else {
          userInfo = {};
        }
        // 默认头像路径 /img/jelon.jpg
        $('loginAvatar').src = userInfo.avatar_url || '/img/github.png';
      }
    },
    list: {
      tpl: [
        '<section class="list-wrap" id="JELON__commentList">',
          '<div class="text-center">正在加载评论</div>',
        '</section>'
      ].join(''),
      /**
       * 评论列表模块视图更新
       * @param  {Number}    page      评论列表当前页码
       * @param  {Number}    comments  当前文章下所有评论总数
       * @param  {Number}    list      当前列表下评论列表数据
       * @param  {Function}  callback  回调
       * @return void(0)
       */
      update: function (page, comments, list, callback) {
        var perNavPageMaxSize = 10;
        var html = '';
        var htmlList = [];
        var pageList = [];
        var allPages = Math.ceil(comments / constants.PER_PAGE);
        if (comments === 0) {
          html = '<div class="text-center">暂无评论</div>';
        } else {
          var item = '';
          var pageItem = '';
          for (var i = 0, len = list.length; i < len; i++) {
            item = [
              '<li class="item">',
                '<div class="user-avatar">',
                  '<a target="_blank" href="' + list[i].user.html_url + '">',
                    '<img src="' + list[i].user.avatar_url + '" alt="user-avatar">',
                  '</a>',
                '</div>',
                '<div class="user-comment">',
                  '<div class="user-comment-header" id="JELON__comment_' + list[i].id + '_reactions">',
                    '<span class="post-name">' + list[i].user.login +  '</span>',
                    '<span class="post-time">' + formatDate('yyyy-MM-dd hh:mm', new Date(list[i].created_at)) + '</span>',
                    '<span class="like" onclick="JELON.Actions.like(' + list[i].id + ')">点赞</span>',
                    '<span class="like-num">' + list[i].reactions.heart + '</span>',
                    '<span class="reply" onclick="JELON.Actions.reply(\'' + list[i].user.login + '\', \'' + (list[i].body_html || list[i].body).replace(/<[^>]+>|\s|[\r\n]/g, ' ') + '\')">回复</span>',
                  '</div>',
                  '<div class="user-comment-body">' + (list[i].body_html || list[i].body) + '</div>',
                '</div>',
              '</li>'
            ].join('');
            htmlList.push(item);
          }
          if (allPages === 1) {
            pageItem = '<a href="javascript: void(0);" class="item current">' + page + '</a>';
            pageList.push(pageItem);
          } else if (allPages <= perNavPageMaxSize) {
            for (var i = 1; i <= allPages; i++) {
              if (i === page) {
                pageItem = '<a href="javascript: void(0);" class="item current">' + page + '</a>';
              } else {
                pageItem = '<a href="javascript: JELON.Actions.pageJump(' + i + ');" class="item">' + i + '</a>';
              }
              pageList.push(pageItem);
            }
            if (page !== 1) {
              pageList.unshift('<a href="javascript: JELON.Actions.pageJump(' + (page - 1) + ');" class="item">上页</a>');
            }
            if (page !== allPages) {
              pageList.push('<a href="javascript: JELON.Actions.pageJump(' + (page + 1) + ');" class="item">下页</a>');
            }
          } else if (allPages > perNavPageMaxSize) {
            if (page <= perNavPageMaxSize) {
              for (var i = 1; i <= perNavPageMaxSize; i++) {
                if (i === page) {
                  pageItem = '<a href="javascript: void(0);" class="item current">' + page + '</a>';
                } else {
                  pageItem = '<a href="javascript: JELON.Actions.pageJump(' + i + ');" class="item">' + i + '</a>';
                }
                pageList.push(pageItem);
              }
              if (page !== 1) {
                pageList.unshift('<a href="javascript: JELON.Actions.pageJump(' + (page - 1) + ');" class="item">上页</a>');
              }
              pageList.push('<span class="more">...</span>');
              pageList.push('<a href="javascript: JELON.Actions.pageJump(' + (page + 1) + ');" class="item">下页</a>');
              pageList.push('<a href="javascript: JELON.Actions.pageJump(' + allPages + ');" class="item">末页</a>');
            } else if (page > perNavPageMaxSize && page <= allPages - perNavPageMaxSize) {
              var mod = page % perNavPageMaxSize;
              var start = Math.floor(page / perNavPageMaxSize) * perNavPageMaxSize + 1;
              var end = Math.ceil(page / perNavPageMaxSize) * perNavPageMaxSize;
              pageList.push('<a href="javascript: JELON.Actions.pageJump(1);" class="item">首页</a>');
              pageList.push('<a href="javascript: JELON.Actions.pageJump(' + (page - 1) + ');" class="item">上页</a>');
              for (var i = start; i <= end; i++) {
                if (i === page) {
                  pageItem = '<a href="javascript: void(0);" class="item current">' + page + '</a>';
                } else {
                  pageItem = '<a href="javascript: JELON.Actions.pageJump(' + i + ');" class="item">' + i + '</a>';
                }
                pageList.push(pageItem);
              }

              pageList.push('<span class="more">...</span>');
              pageList.push('<a href="javascript: JELON.Actions.pageJump(' + (page + 1) + ');" class="item">下页</a>');
              pageList.push('<a href="javascript: JELON.Actions.pageJump(' + allPages + ');" class="item">末页</a>');
            } else if (page > perNavPageMaxSize && page > allPages - perNavPageMaxSize) {
              var start = allPages - perNavPageMaxSize + 1;
              var end = allPages;
              pageList.push('<a href="javascript: JELON.Actions.pageJump(1);" class="item">首页</a>');
              pageList.push('<a href="javascript: JELON.Actions.pageJump(' + (page - 1) + ');" class="item">上页</a>');
              for (var i = start; i <= end; i++) {
                if (i === page) {
                  pageItem = '<a href="javascript: void(0);" class="item current">' + page + '</a>';
                } else {
                  pageItem = '<a href="javascript: JELON.Actions.pageJump(' + i + ');" class="item">' + i + '</a>';
                }
                pageList.push(pageItem);
              }
              if (page !== allPages) {
                pageList.push('<a href="javascript: JELON.Actions.pageJump(' + (page + 1) + ');" class="item">下页</a>');
              }
            }
          }
          html = [
            '<header class="list-header">总共 <span class="comments-num" id="JELON__commentsNum">' + JL.issueComments + '</span> 条评论</header>',
            '<ul class="list">',
              htmlList.join(''),
            '</ul>',
            '<div class="page-nav">',
              pageList.join(''),
            '</div>'
          ].join('');
        }
        $('JELON__commentList').innerHTML = html;
        if (localStorage.getItem(constants.USER_INFO_KEY)) {
          callback && callback();
        }
      },
      reactionUpdate: function (commentId, reactions) {
        var userInfo = localStorage.getItem(constants.USER_INFO_KEY);
        if (userInfo) {
          userInfo = JSON.parse(userInfo);
        } else {
          return;
        }
        var userId = userInfo.id;
        for (var i = 0, len = reactions.length; i < len; i++) {
          if (userId === reactions[i].user.id) {
            addClass($('JELON__comment_' + commentId + '_reactions').getElementsByClassName('like')[0], 'liked');
            $('JELON__comment_' + commentId + '_reactions').getElementsByClassName('like')[0].innerHTML = '已赞';
            break;
          }
        }
      },
      addOne: function (data) {
        var oLi = document.createElement('li');
        oLi.className = 'item';
        var item = [
          '<div class="user-avatar">',
            '<a target="_blank" href="' + data.user.html_url + '">',
              '<img src="' + data.user.avatar_url + '" alt="user-avatar">',
            '</a>',
          '</div>',
          '<div class="user-comment">',
            '<div class="user-comment-header" id="JELON__comment_' + data.id + '_reactions">',
              '<span class="post-name">' + data.user.login +  '</span>',
              '<span class="post-time">' + formatDate('yyyy-MM-dd hh:mm', new Date(data.created_at)) + '</span>',
              '<span class="like" onclick="JELON.Actions.like(' + data.reactions.heart + ')">点赞</span>',
              '<span class="like-num">' + data.reactions.heart + '</span>',
              '<span class="reply" onclick="JELON.Actions.reply(\'' + data.user.login + '\', \'' + (data.body_html || data.body).replace(/<[^>]+>|\s|[\r\n]/g, ' ') + '\')">回复</span>',
            '</div>',
            '<div class="user-comment-body">' + (data.body_html || data.body) + '</div>',
          '</div>'
        ].join('');
        oLi.innerHTML = item;
        var oUl = $('JELON__commentList').getElementsByTagName('ul')[0];
        if (oUl) {
          oUl.insertBefore(oLi, oUl.firstChild);
          $('JELON__commentsNum').innerHTML = JL.issueComments + 1;
        } else {
          $('JELON__commentList').innerHTML = [
            '<header class="list-header">总共 <span class="comments-num" id="JELON__commentsNum">' + (JL.issueComments + 1) + '</span> 条评论</header>',
            '<ul class="list">',
              '<li class="item">',
                item,
              '</li>',
            '</ul>'
          ].join('');
        }
      }
    },
    signBar: {
      tpl: [
        '<div class="sign-bar" id="JELON__commentSignBar">',
        '</div>'
      ].join(''),
      update: function () {
        var token = localStorage.getItem(constants.ACCESS_TOKEN_KEY);
        var userInfo = localStorage.getItem(constants.USER_INFO_KEY);
        var html = '';
        if (token && userInfo) {
          userInfo = JSON.parse(userInfo);
          html = [
            '<span class="sign-txt" title="' + userInfo.login + '">GitHub 已登录!</span>',
            '<span class="sign-link" onclick="JELON.Actions.signOut()">退出</span>'
          ].join('');
        } else {
          html = [
            '<span class="sign-txt">GitHub 未登录?</span>',
            '<a href="https://github.com/login/oauth/authorize?scope=public_repo&redirect_uri=',
              location.href.indexOf('?') !== -1 ? encodeURIComponent(location.href.substring(0, location.href.indexOf('?'))) : encodeURIComponent(location.href),
              '&client_id=' + JL.options.clientId + '&client_secret=' + JL.options.clientSecret + '" class="sign-link">',
              '登录',
            '</a>'
          ].join('');
        }
        $('JELON__commentSignBar').innerHTML = html;
      }
    },
    tips: {
      tpl: '<section class="tips clearfix" id="JELON__comment_tips">注：评论支持 markdown 语法！</section>',
      update: function () {
        var userInfo = localStorage.getItem(constants.USER_INFO_KEY);
        var handler = '';
        // 如果文章还没关联 issue 并且登录账号是自己时
        if (userInfo && JSON.parse(userInfo).login === JL.options.owner && JL.issueNumber === 0) {
          handler = '<a href="javascript: JELON.Actions.createIssue();" class="init" title="文章关联 issue">初始化评论</a>';
        }
        $('JELON__comment_tips').innerHTML = handler + '注：评论支持 markdown 语法！';
      }
    },
    flashTitle: function (title) {
      var counter = 0;
      document.title = title + '...';
      var timer = setInterval(function () {
        counter++;
        if (counter % 3 === 0) {
          document.title = title + '...';
        } else if (counter % 3 === 1) {
          document.title = title + '..';
        } else if (counter % 3 === 2) {
          document.title = title + '.';
        }
      }, 100);
    },
    loading: {
      create: function (oParent) {
        oParent = oParent || document.body;
        var oLoading = document.createElement('div');
        oLoading.className = 'loading-mask';
        oLoading.id = 'JELON__loadingMask';
        oLoading.innerHTML = '<div class="loading-icon"><img src="/img/loading.gif" width="50" height="50" alt="加载中" ></div>';
        oParent.appendChild(oLoading);
      },
      remove: function () {
        var oLoading = $('JELON__loadingMask');
        oLoading.parentNode.removeChild(oLoading);
      }
    }
  };
  JL.Actions = {
    init: function () {
      var code = queryUrl('code');
      JL.Renders.signBar.update();
      JL.Renders.box.update();
      // if code，继续GitHub 授权
      if (code) {
        JL.Renders.loading.create();
        JL.Renders.flashTitle('登录中');
        JL.Requests.getAccessToken({
          client_id: JL.options.clientId,
          client_secret: JL.options.clientSecret,
          code: code
        }, function (res) {
          if (res.access_token || res.data) {
            if (res.data) {
              res.access_token = res.data.access_token;
            }
            localStorage.setItem(constants.ACCESS_TOKEN_KEY, res.access_token);       // 保存 access_token 至 localStorage
            JL.Requests.getUserInfo({ access_token: res.access_token }, function (res) {
              if (res.login) {
                localStorage.setItem(constants.USER_INFO_KEY, JSON.stringify(res));     // 保存用户信息到 localStorage
                location.href = location.href.substring(0, location.href.indexOf('?'));
                JL.Renders.loading.remove();
              }
            });
          } else {
            // 登录失败
            location.href = location.href.substring(0, location.href.indexOf('?'));
            JL.Renders.loading.remove();
          }
        });
      } else {
        JL.Requests.getIssueNumberByLabel(JL.options.label, function (res) {
          if (res.length > 0) {
            var number = res[0].number;
            var comments = res[0].comments; // 该 issue 下所有评论数
            JL.issueNumber = number;
            JL.issueComments = comments;
            JL.Requests.getCommentListByIssueNumber(number, {
              page: 1,
              per_page: constants.PER_PAGE
            }, function (list) {
              JL.Renders.list.update(1, comments, list, function () {
                for (var i = 0, len = list.length; i < len; i++) {
                  (function (commentId) {
                    JL.Requests.getReactionsByCommentId(commentId, { content: 'heart' }, function (reactions) {
                      JL.Renders.list.reactionUpdate(commentId, reactions);
                    });
                  }(list[i].id));
                }
              });
            });
          } else {
            // 授权码失效
            if (typeof res !== 'object') {
              localStorage.removeItem(constants.ACCESS_TOKEN_KEY);
              localStorage.removeItem(constants.USER_INFO_KEY);
              JL.Renders.signBar.update();
              JL.Renders.box.update();
              console.warn('登录失败，请稍后刷新再试');
            } else {
              JL.Renders.list.update(1, 0, []);
              JL.Renders.tips.update();
            }
          }
        });
      }
    },
    signOut: function () {
      localStorage.removeItem(constants.ACCESS_TOKEN_KEY);
      localStorage.removeItem(constants.USER_INFO_KEY);
      JL.Renders.signBar.update();
      JL.Renders.box.update();
    },
    pageJump: function (page) {
      JL.Requests.getCommentListByIssueNumber(JL.issueNumber, {
        page: Number(page),
        per_page: constants.PER_PAGE
      }, function (list) {
        JL.Renders.list.update(page, JL.issueComments, list, function () {
          for (var i = 0, len = list.length; i < len; i++) {
            (function (commentId) {
              JL.Requests.getReactionsByCommentId(commentId, { content: 'heart' }, function (reactions) {
                JL.Renders.list.reactionUpdate(commentId, reactions);
              });
            }(list[i].id));
          }
        });
      });
    },
    editPreviewSwitch: function (flag) {
      if (flag === 'edit') {
        removeClass('JELON__previewSwitcher', 'on');
        addClass('JELON__editSwitcher', 'on');
        removeClass('JELON__previewBox', 'show');
        addClass('JELON__editBox', 'show');
      } else {
        removeClass('JELON__editSwitcher', 'on');
        addClass('JELON__previewSwitcher', 'on');
        removeClass('JELON__editBox', 'show');
        addClass('JELON__previewBox', 'show');
        var text = $('JELON__editBox').value.trim();
        text = htmlFilter(text);
        if (text) {
          JL.Requests.markdown({
            text: text,
            mode: 'markdown',
            context: 'github/gollum'
          }, function (res) {
            $('JELON__previewBox').innerHTML = res;
          });
        } else {
          $('JELON__previewBox').innerHTML = '';
        }
      }
    },
    postComment: function () {
      var accessToken = localStorage.getItem(constants.ACCESS_TOKEN_KEY);
      var userInfo = localStorage.getItem(constants.USER_INFO_KEY);
      if (!accessToken || !userInfo) {
        alert('请先登录哦..!^_^');
        return;
      }
      var body = $('JELON__editBox').value.trim();
      body = htmlFilter(body);
      if (body) {
        JL.Renders.loading.create();
        if (JL.issueNumber !== 0) {
          JL.Requests.createComment(JL.issueNumber, {
            body: body
          }, function (res) {
            if (res.id) {
              JL.Renders.list.addOne(res);
              JL.issueComments++;
              $('JELON__editBox').value = '';
              $('JELON__previewBox').innerHTML = '';
            }
            JL.Renders.loading.remove();
          });
        } else {
          // 如果还没有创建 issue，先创建 issue
          JL.Requests.createIssue({
            title: document.title,
            body: location.href,
            labels: [ (JL.options.label || location.href) ]
          }, function (res) {
            if (res.number) {
              JL.issueNumber = res.number
              JL.Requests.createComment(JL.issueNumber, {
                body: body
              }, function (json) {
                if (res.id) {
                  JL.Renders.list.addOne(json);
                  JL.issueComments++;
                  $('JELON__editBox').value = '';
                  $('JELON__previewBox').innerHTML = '';
                }
                JL.Renders.loading.remove();
              });
            }
          });
        }
      }
    },
    like: function (commentId) {
      var oLiked = $('JELON__comment_' + commentId + '_reactions').getElementsByClassName('liked');
      var oLike = $('JELON__comment_' + commentId + '_reactions').getElementsByClassName('like')[0];
      var oNum = $('JELON__comment_' + commentId + '_reactions').getElementsByClassName('like-num')[0];
      var accessToken = localStorage.getItem(constants.ACCESS_TOKEN_KEY);
      var userInfo = localStorage.getItem(constants.USER_INFO_KEY);
      if (oLiked.length) {
        return false;
      } else {
        if (accessToken && userInfo) {
          JL.Requests.createReaction(commentId, { content: 'heart' }, function (res) {
            if (res.content === 'heart') {
              addClass(oLike, 'liked');
              oLike.innerHTML = '已赞';
              oNum.innerHTML = Number(oNum.innerHTML) + 1;
            }
          });
        }
      }
    },
    createIssue: function () {
      JL.Renders.loading.create();
      JL.Requests.createIssue({
        title: document.title,
        body: location.href,
        labels: [ (JL.options.label || location.href) ]
      }, function (json) {
        if (json.number) {
          JL.issueNumber = json.number;
          JL.Renders.tips.update();
        }
        JL.Renders.loading.remove();
      });
    },
    reply: function (people, content) {
      var accessToken = localStorage.getItem(constants.ACCESS_TOKEN_KEY);
      var userInfo = localStorage.getItem(constants.USER_INFO_KEY);
      if (!accessToken || !userInfo) {
        return;
      }
      JL.Actions.editPreviewSwitch('edit');
      $('JELON__editBox').value = '';
      $('JELON__editBox').focus();
      $('JELON__editBox').value = [
        '@' + people + '\n',
        '> ' + content + '\n',
        '\n'
      ].join('');
      $('JELON__previewBox').innerHTML = '';
    }
  };
  var createSuccessCb = function(callback){
    return function (res) {
      if (typeof res === 'string') {
        if (window.JSON) {
          res = JSON.parse(res);
        } else {
          res = eval('(' + res + ')');
        }
      }
      callback && callback(res);
    }
  }
  JL.Requests = {
    getIssueNumberByLabel: function (label, callback) {
      ajax({
        url: constants.API_HOST + '/repos/' + JL.options.owner + '/' + JL.options.repo + '/issues',
        method: 'GET',
        data: {
          labels: [ label ],
          rnd: Math.random()
        },
        success: createSuccessCb(callback),
        fail: callback
      });
    },
    createIssue: function (data, callback) {
      ajax({
        url: constants.API_HOST + '/repos/' + JL.options.owner + '/' + JL.options.repo + '/issues',
        method: 'POST',
        data: data,
        success: createSuccessCb(callback),
        fail: callback
      });
    },
    getCommentListByIssueNumber: function (number, data, callback) {
      ajax({
        url: constants.API_HOST + '/repos/' + JL.options.owner + '/' + JL.options.repo + '/issues/' + number + '/comments',
        method: 'GET',
        data: data,
        success: createSuccessCb(callback),
        fail: callback
      });
    },
    getReactionsByCommentId: function (id, data, callback) {
      if (typeof data === 'object' && !data.rnd) {
        data.rnd = Math.random();
      }
      ajax({
        url: constants.API_HOST + '/repos/' + JL.options.owner + '/' + JL.options.repo + '/issues/comments/' + id + '/reactions',
        method: 'GET',
        data: data,
        success: createSuccessCb(callback),
        fail: callback
      });
    },
    editIssue: function (number, data, callback) {
      ajax({
        url: constants.API_HOST + '/repos/' +  JL.options.owner + '/' + JL.options.owner + '/issues/' + number,
        method: 'POST',
        data: data,
        success: createSuccessCb(callback),
        fail: callback
      });
    },
    markdown: function (data, callback) {
      ajax({
        url: constants.API_HOST + '/markdown',
        method: 'POST',
        data: data,
        success: callback,
        fail: callback
      });
    },
    getAccessToken: function (data, callback) {
      ajax({
        // url: 'https://gh-oauth.imsun.net/',
        url: 'https://cors-anywhere.herokuapp.com/https://github.com/login/oauth/access_token',
        method: 'POST',
        headers: {
          'Accept': 'application/json'
        },
        data: data,
        success: createSuccessCb(callback),
        fail: callback
      });
    },
    getUserInfo: function (data, callback) {
      ajax({
        url: constants.API_HOST + '/user',
        method: 'GET',
        data: data,
        success: createSuccessCb(callback),
        fail: callback
      });
    },
    createComment: function (number, data, callback) {
      ajax({
        url: constants.API_HOST + '/repos/' + JL.options.owner + '/' + JL.options.repo + '/issues/' + number + '/comments',
        method: 'POST',
        data: data,
        success: createSuccessCb(callback),
        fail: callback
      });
    },
    createReaction: function (commentId, data, callback) {
      ajax({
        url: constants.API_HOST + '/repos/' + JL.options.owner + '/' + JL.options.repo + '/issues/comments/' + commentId + '/reactions',
        method: 'POST',
        data: data,
        success: createSuccessCb(callback),
        fail: callback
      });
    }
  };
  JL.Comment = function (options) {
    JL.options = options || {};
    var $container = $('comments');
    if (options.container) {
      if (typeof options.container === 'object') {
        $container = options.container;
      } else if (typeof options.container === 'string') {
        if (/^#/.test(options.container)) {
          $container = $(options.container.replace(/^#/, ''));
        } else {
          $container = $(options.container);
        }
      } else {
        $container = $('comments');
      }
    }
    $container.innerHTML = [
      this.Renders.signBar.tpl,
      this.Renders.box.tpl,
      this.Renders.tips.tpl,
      this.Renders.list.tpl
    ].join('');
    JL.Actions.init();
  };
})(JELON);
