text: import { Meteor } from 'meteor/meteor';
  import { _ } from 'meteor/underscore';
  
  import { ItemsFilter } from './ItemsFilter';
  
  import { TOPIC_KEYWORDS } from './FilterKeywords';
  
  export class TopicsFilter {
  
      constructor() {
          this.isCaseSensitive = false;
          this.itemsFilter = new ItemsFilter();
      }
  
      filter(docs, parser) {
          if (!parser) { throw new Meteor.Error('illegal-state', 'Please inject a query parser.'); }
          if (!docs) { docs = []; }
  
  
          this.isCaseSensitive = parser.isCaseSensitive();
          return docs.filter(doc => {
              return this.docMatchesSearchTokens(doc, parser.getSearchTokens())
                  && this.docMatchesLabelTokens(doc, parser.getLabelTokens())
                  && this.docMatchesFilterTokens(doc, parser.getFilterTokens());
          });
      }
  
      docMatchesSearchTokens(doc, searchTokens) {
          for (let i=0; i < searchTokens.length; i++) {
              let token = this._toUpper(searchTokens[i]);
              let subject = this._toUpper(doc.subject);
  
              let hasMatchingInfoItems =
                  this.itemsFilter.filterWithParams(doc.infoItems, this.isCaseSensitive, [token]).length > 0;
  
              if (
                  (subject.indexOf(token) === -1
                  && !hasMatchingInfoItems)
              ) {
                  return false;
              }
          }
          return true;
      }
  
      _toUpper(str) {
          return (this.isCaseSensitive) ? str : str.toUpperCase();
      }
  
  
      docMatchesLabelTokens(doc, labelTokens) {
          for (let i=0; i < labelTokens.length; i++) {
              let token = labelTokens[i];
              let hasMatchingInfoItems =
                  this.itemsFilter.filterWithParams(doc.infoItems, this.isCaseSensitive, [], [token]).length > 0;
              if (!hasMatchingInfoItems) {
                  return false;
              }
          }
          return true;
      }
  
      docMatchesFilterTokens(doc, filterTokens) {
          for (let i=0; i < filterTokens.length; i++) {
              let filter = filterTokens[i];
  
              switch (filter.key) {
              case TOPIC_KEYWORDS.IS.key:
              {
                  if (!this.constructor._docMatchesKeyword_IS(doc, filter.value)) {
                      return false;
                  }
                  break;
              }
              case TOPIC_KEYWORDS.HAS.key:
              {
                  if (!this._docMatchesKeyword_HAS(doc, filter.value)) {
                      return false;
                  }
                  break;
              }
              case TOPIC_KEYWORDS.USER.key:
              {
                  if (!this._docMatchesKeywords_USER(doc, filter)) {
                      return false;
                  }
                  break;
              }
              case TOPIC_KEYWORDS.DO.key:
              {
                  break;
              }
              default: throw new Meteor.Error('illegal-state', `Unknown filter keyword: ${filter.key}`);
              }
          }
  
          return true;
      }
  
      _docMatchesKeywords_USER(doc, filter) {
          if (!doc.responsibles) { return false; }
          let respStr = doc.responsibles.reduce((acc, resp) => { return acc + resp; }, '');
          return ( (filter.ids && _.intersection(doc.responsibles, filter.ids).length > 0)
                      || (filter.value && this._toUpper(respStr).indexOf(this._toUpper(filter.value)) !== -1) );
      }
  
  
      static _docMatchesKeyword_IS(doc, value) {
          switch (value) {
          case 'open':
              return doc.isOpen;
          case 'closed':
              // explicit comparison required to skip info items (which has no isOpen property)
              return doc.isOpen === false;
          case 'new':
              return doc.isNew;
          default: throw new Meteor.Error('illegal-state', `Unknown filter value: ${value}`);
          }
      }
  
      _docMatchesKeyword_HAS(doc, value) {
          switch (value) {
          case 'item':
              return doc.infoItems.length > 0;
          case 'info':
          case 'action':
          {
              let items = this.itemsFilter.filterWithParams(
                  doc.infoItems,
                  this.isCaseSensitive,
                  [],
                  [],
                  [{key: 'is', value: value}]);
              return items.length > 0;
          }
          default: throw new Meteor.Error('illegal-state', `Unknown filter value: ${value}`);
          }
      }
  
  
  }