// ==UserScript==
// @name         豆瓣小组功能增强
// @version      0.2.1.0
// @license      MIT
// @namespace    https://tcatche.github.io/
// @description  豆瓣小组展示功能增强:高亮包含指定关键字的帖子;隐藏包含指定关键字的帖子;去除标题省略号,展示全部文本;新标签页打开帖子;展示是否是楼主的标识;展示楼层号;淡化已读帖子标题;增加帖子内内容跳转; 去广告功能
// @author       tcatche
// @match        https://www.douban.com/group/*
// @homepageURL  https://github.com/tcatche/douban-group-enhance
// @supportURL   https://github.com/tcatche/douban-group-enhance/issues
// @grant        none
// @downloadURL https://update.greasyfork.icu/scripts/381514/%E8%B1%86%E7%93%A3%E5%B0%8F%E7%BB%84%E5%8A%9F%E8%83%BD%E5%A2%9E%E5%BC%BA.user.js
// @updateURL https://update.greasyfork.icu/scripts/381514/%E8%B1%86%E7%93%A3%E5%B0%8F%E7%BB%84%E5%8A%9F%E8%83%BD%E5%A2%9E%E5%BC%BA.meta.js
// ==/UserScript==
(function() {
  const utils = {
    // save user config
    saveConfig: config => {
      const configString = JSON.stringify(config);
      localStorage.setItem('douban_group_enhance_config', configString);
    },
    // load user config
    getConfig: () => {
      const configString = localStorage.getItem('douban_group_enhance_config');
      const oldConfigString = localStorage.getItem('douban_group_filter_config');
      try {
        const config = JSON.parse(configString || oldConfigString);
        return config;
      } catch (e) {
        return {};
      }
    },
    bindedEles: [],
    bindClick: function(selector, callback) {
      this.bindedEles.push(selector);
      $(selector).click(callback);
    },
    unbindClick: (selector) => {
      $(selector).unbind();
    },
    unbindAllClick: function() {
      this.bindedEles.forEach(selector => {
        $(selector).click(callback);
      })
    }
  }
  const createEnhancer = () => {
  
    // run user filters
    const runFilter = (config, self) => {
      const title = self.attr('title') || '';
      const isInInclude = title => (config.include || []).find(keyword => title.indexOf(keyword) >= 0);
      const isInDeclude = title => (config.declude || []).find(keyword => title.indexOf(keyword) >= 0);
      const isTitleInInclude = isInInclude(title);
      const isTitleInDeclude = isInDeclude(title);
      if (isTitleInInclude && !isTitleInDeclude) {
        self.addClass('douban_group_enhance_highlight');
      }
      if (isInDeclude(title)) {
        self.parents('tr').hide();
      }
    }
  
    // open in new tab
    const runOpenInNewTab = (config, self) => {
      if (config.openInNewTab) {
        self.attr('target', '_blank');
      }
    }
  
    // show full title without cliped!
    const runShowFullTitle = (config, self) => {
      if (config.showFullTitle) {
        const title = self.attr('title') || self.text();
        self.text(title);
      }
    }
    // run fade visited topic
    const runFadeVisitedTitle = config => {
      if (config.fadeVisited) {
        if ($('#fadeVisitedStyle').length === 0) {
          $('body').append(`
            
          `);
        }
      } else {
        $('#fadeVisitedStyle').remove();
      }
    }
  
    // show reply number
    const runShowReplyNumber = (options, self, index) => {
      if (options.config.showReplyNumber) {
        const replyHead = self.find('h4')[0];
        const isInserted = $(replyHead).find('.douban_group_enhance_replay_number').length > 0;
        if (!isInserted) {
          const start = +(options.params.start || 0);
          const replayNumber = start + 1 + index;
          $(replyHead).append(`${replayNumber}楼`);
        }
      } else {
        $('.douban_group_enhance_replay_number').remove();
      }
    }
  
    // show if is topic owner 
    const runShowOwnerTag = (options, self) => {
      if (options.config.showOwnerTag) {
        const replyHead = self.find('h4')[0];
        const isInserted = $(replyHead).find('.douban_group_enhance_owner_tag').length > 0;
        if (!isInserted) {
          const replyName = self.find('h4 a').text().trim();
          if (replyName === options.topicUser) {
            $(replyHead).append('楼主');
          }
        }
      } else {
        $('.douban_group_enhance_owner_tag').remove();
      }
    }
  
    // add jump to top, comments and pager button
    const runAddJumptoButton = options => {
      if (options.config.jumpTo) {
        const isAdded = $('#douban_group_enhance_jump').length > 0;
        if (!isAdded) {
          $(document.body).append(`
            
              跳转到:
              标题/
              /
              页尾
            
          `);
          setTimeout(() => {
            utils.bindClick('.douban_group_enhance_jump_target_title', e => {
              $('h1')[0].scrollIntoView({behavior: 'smooth'});
            });
            utils.bindClick('.douban_group_enhance_jump_target_comments', e => {
              $('.topic-reply ')[0].scrollIntoView({behavior: 'smooth'});
            });
            utils.bindClick('.douban_group_enhance_jump_target_end', e => {
              $('#footer')[0].scrollIntoView({behavior: 'smooth'});
            });
          }, 0)
        }
      } else {
        $('.douban_group_enhance_jump').remove();
      }
    }
  
    // run remove google ads
    const runRemoveAd = options => {
      if (options.config.removeAd) {
        setTimeout(function() {
          $('[ad-status]').remove()
        })
      }
    }
    const runEnhancer = config => {
      const isTopicDetailPage = location.pathname.indexOf('/group/topic/') >= 0;
      const search = location.search  ? location.search.substr(1) : '';
      const params = {};
      search.split('&').filter(v => !!v).map(item => {
        const items = item.split('=');
        if (items.length >= 1) {
          params[items[0]] = items[1];
        }
      });
      const global = {
        config: config,
        params: params,
      };
      runRemoveAd(global);
      if (isTopicDetailPage) {
        // 帖子内容
        $('#comments li').each(function(index) {
          global.topicUser = $('.topic-doc .from > a').text().trim();
          const $this = $(this);
          runShowReplyNumber(global, $this, index);
          runShowOwnerTag(global, $this);
        });
        runAddJumptoButton(global);
      } else {
        // 帖子列表
        $('.topics .td-subject a, .title a').each(function() {
          const $this = $(this);
          runFilter(config, $this);
          runOpenInNewTab(config, $this);
          runShowFullTitle(config, $this);
        });
        runFadeVisitedTitle(config);
      }
    }
    // init form elements
    const initDom = () => {
      // init config dom
      let configDivHtml = `
        
          
          
        
      `;
      let styleHtml = `
        
      `;
      $(document.body).append(configDivHtml);
      $(document.body).append(styleHtml);
      
      // init config btn
      const insertPos = $('#db-global-nav .top-nav-doubanapp');
      if (insertPos && insertPos[0]) {
        $(insertPos[0]).after('
小组增强插件设置
');
      }
    }
    // init dom events
    const initDomEvents = () => {
      const $contain = $('#douban_group_enhance_container');
      const $body = $(document.body);
      // bind events
      utils.bindClick('#douban_group_enhance_config', e => {
        $contain.show();
        $body.css('overflow', 'hidden');
      });
      utils.bindClick('#douban_group_enhance_cancel', e => {
        $contain.hide();
        $body.css('overflow', 'initial');
      });
      utils.bindClick('.douban_group_enhance_mask', e => {
        $contain.hide();
        $body.css('overflow', 'initial');
      });
      utils.bindClick('#douban_group_enhance_sure', e => {
        const config = {
          include: $('#douban_group_enhance_container textarea')[0].value.split(' ').filter(v => !!v),
          declude: $('#douban_group_enhance_container textarea')[1].value.split(' ').filter(v => !!v),
          openInNewTab: $('#openInNewTab')[0].checked,
          showFullTitle: $('#showFullTitle')[0].checked,
          showReplyNumber: $('#showReplyNumber')[0].checked,
          showOwnerTag: $('#showOwnerTag')[0].checked,
          fadeVisited: $('#fadeVisited')[0].checked,
          jumpTo: $('#jumpTo')[0].checked,
          removeAd: $('#removeAd')[0].checked,
        }
        utils.saveConfig(config);
        runEnhancer(config);
        $contain.hide();
        $body.css('overflow', 'initial');
      });
    }
    // init form values
    const initDomValue = config => {
      $('#douban_group_enhance_container textarea')[0].value = (config.include || []).join(' ');
      $('#douban_group_enhance_container textarea')[1].value = (config.declude || []).join(' ');
      $('#openInNewTab')[0].checked = config.openInNewTab;
      $('#showFullTitle')[0].checked = config.showFullTitle;
      $('#showReplyNumber')[0].checked = config.showReplyNumber;
      $('#showOwnerTag')[0].checked = config.showOwnerTag;
      $('#fadeVisited')[0].checked = config.fadeVisited;
      $('#jumpTo')[0].checked = config.jumpTo;
      $('#removeAd')[0].checked = config.removeAd;
    }
    const init = () => {
      const config = utils.getConfig() || {};
      initDom();
      initDomValue(config);
      initDomEvents();
      runEnhancer(config);
    }
    const destory = () => {
      // remove dom events
      utils.unbindAllClick();
      // remove all added elements
      $('#.douban_group_added').remove();
    }
    return {
      init,
      destory,
      _version: '0.2.1.0'
    }
  }
  // init
  if (window.doubanEnhancer) {
    const enhancer = createEnhancer();
    if (!doubanEnhancer._version) {
      doubanEnhancer._version = '0'
    }
    if (window.doubanEnhancer._version < enhancer._version) {
      if (doubanEnhancer.destory) {
        doubanEnhancer.destory();
      }
      window.doubanEnhancer = enhancer;
      doubanEnhancer.init();
    }
  } else {
    window.doubanEnhancer = createEnhancer();
    doubanEnhancer.init();
  }
})();