{"size": 3793, "ext": "es6", "max_stars_repo_path": "packages/client-app/src/services/search/search-query-backend-imap.es6", "max_stars_repo_name": "cnheider/nylas-mail", "max_stars_repo_stars_event_min_datetime": "2015-10-05T16:35:18.000Z", "max_stars_repo_stars_event_max_datetime": "2017-01-27T15:33:55.000Z", "max_issues_repo_path": "packages/client-app/src/services/search/search-query-backend-imap.es6", "max_issues_repo_name": "tashby/nylas-mail", "max_issues_repo_issues_event_min_datetime": "2015-10-05T17:37:34.000Z", "max_issues_repo_issues_event_max_datetime": "2017-01-27T18:36:01.000Z", "max_forks_repo_path": "packages/client-app/src/services/search/search-query-backend-imap.es6", "max_forks_repo_name": "tashby/nylas-mail", "max_forks_repo_forks_event_min_datetime": "2015-10-05T17:14:18.000Z", "max_forks_repo_forks_event_max_datetime": "2017-01-24T19:36:40.000Z"}
{"max_stars_count": 24369, "max_issues_count": 3209, "max_forks_count": 1308, "avg_line_length": 21.0722222222, "max_line_length": 79, "alphanum_fraction": 0.6190350646}
import _ from 'underscore'
import {
  AndQueryExpression,
  SearchQueryExpressionVisitor,
} from './search-query-ast';

const TOP = 'top';

class IMAPSearchQueryFolderFinderVisitor extends SearchQueryExpressionVisitor {
  visit(root) {
    const result = this.visitAndGetResult(root);
    if (result === TOP) {
      return 'all';
    }
    return result;
  }

  visitAnd(node) {
    const lhs = this.visitAndGetResult(node.e1);
    const rhs = this.visitAndGetResult(node.e2);
    if (lhs === TOP) {
      this._result = rhs;
      return;
    }
    if (rhs === TOP) {
      this._result = lhs;
      return;
    }
    this._result = _.intersection(lhs, rhs);
  }

  visitOr(node) {
    const lhs = this.visitAndGetResult(node.e1);
    const rhs = this.visitAndGetResult(node.e2);
    if (lhs === TOP || rhs === TOP) {
      this._result = TOP;
      return;
    }
    this._result = _.union(lhs, rhs);
  }

  visitIn(node) {
    const folderName = this.visitAndGetResult(node.text);
    this._result = [folderName];
  }

  visitFrom(/* node */) {
    this._result = TOP;
  }

  visitTo(/* node */) {
    this._result = TOP;
  }

  visitSubject(/* node */) {
    this._result = TOP;
  }

  visitGeneric(/* node */) {
    this._result = TOP;
  }

  visitText(node) {
    this._result = node.token.s;
  }

  visitUnread(/* node */) {
    this._result = TOP;
  }

  visitStarred(/* node */) {
    this._result = TOP;
  }

  visitHasAttachment(/* node */) {
    this._result = TOP;
  }
}

class IMAPSearchQueryExpressionVisitor extends SearchQueryExpressionVisitor {
  constructor(folder) {
    super();
    this._folder = folder;
  }

  visit(root) {
    const result = this.visitAndGetResult(root);
    if (root instanceof AndQueryExpression) {
      return result;
    }
    return [result];
  }

  visitAnd(node) {
    const lhs = this.visitAndGetResult(node.e1);
    const rhs = this.visitAndGetResult(node.e2);
    this._result = [];
    if (node.e1 instanceof AndQueryExpression) {
      this._result = this._result.concat(lhs);
    } else {
      this._result.push(lhs);
    }

    if (node.e2 instanceof AndQueryExpression) {
      this._result = this._result.concat(rhs);
    } else {
      this._result.push(rhs);
    }
  }

  visitOr(node) {
    const lhs = this.visitAndGetResult(node.e1);
    const rhs = this.visitAndGetResult(node.e2);
    this._result = ['OR', lhs, rhs];
  }

  visitFrom(node) {
    const text = this.visitAndGetResult(node.text);
    this._result = ['FROM', text];
  }

  visitTo(node) {
    const text = this.visitAndGetResult(node.text);
    this._result = ['TO', text];
  }

  visitSubject(node) {
    const text = this.visitAndGetResult(node.text);
    this._result = ['SUBJECT', text];
  }

  visitGeneric(node) {
    const text = this.visitAndGetResult(node.text);
    this._result = ['TEXT', text];
  }

  visitText(node) {
    this._result = node.token.s;
  }

  visitUnread(node) {
    this._result = node.status ? 'UNSEEN' : 'SEEN';
  }

  visitStarred(node) {
    this._result = node.status ? 'FLAGGED' : 'UNFLAGGED';
  }

  visitIn(node) {
    const text = this.visitAndGetResult(node.text);
    this._result = text === this._folder.name ? 'ALL' : '!ALL';
  }

  visitHasAttachment(/* node */) {
    this._result = ['OR',
      ['HEADER', 'Content-Type', 'multipart/mixed'],
      ['HEADER', 'Content-Type', 'multipart/related'],
    ];
  }
}


export default class IMAPSearchQueryBackend {
  static ALL_FOLDERS() {
    return 'all';
  }

  static compile(ast, folder) {
    return (new IMAPSearchQueryBackend()).compile(ast, folder);
  }

  static folderNamesForQuery(ast) {
    return (new IMAPSearchQueryFolderFinderVisitor()).visit(ast);
  }

  compile(ast, folder) {
    return (new IMAPSearchQueryExpressionVisitor(folder)).visit(ast);
  }
}
