import React from 'react';
import _ from 'underscore';

import {Actions,
  AccountStore,
  MailRulesStore,
  MailRulesTemplates,
  TaskQueue,
  ReprocessMailRulesTask} from 'nylas-exports';

import {Flexbox,
  EditableList,
  RetinaImg,
  ScrollRegion,
  ScenarioEditor} from 'nylas-component-kit';

const {
  ActionTemplatesForAccount,
  ConditionTemplatesForAccount,
} = MailRulesTemplates;


class PreferencesMailRules extends React.Component {
  static displayName = 'PreferencesMailRules';

  constructor() {
    super();
    this.state = this._getStateFromStores();
  }

  componentDidMount() {
    this._unsubscribers = [];
    this._unsubscribers.push(MailRulesStore.listen(this._onRulesChanged));
    this._unsubscribers.push(TaskQueue.listen(this._onTasksChanged));
  }

  componentWillUnmount() {
    this._unsubscribers.forEach(unsubscribe => unsubscribe());
  }

  _getStateFromStores() {
    const accounts = AccountStore.accounts();
    const state = this.state || {};
    let {currentAccount} = state;
    if (!accounts.find(acct => acct === currentAccount)) {
      currentAccount = accounts[0];
    }
    const rules = MailRulesStore.rulesForAccountId(currentAccount.id);
    const selectedRule = this.state && this.state.selectedRule ? rules.find(r => r.id === this.state.selectedRule.id) : rules[0];

    return {
      accounts: accounts,
      currentAccount: currentAccount,
      rules: rules,
      selectedRule: selectedRule,
      tasks: TaskQueue.findTasks(ReprocessMailRulesTask, {}),
      actionTemplates: ActionTemplatesForAccount(currentAccount),
      conditionTemplates: ConditionTemplatesForAccount(currentAccount),
    }
  }

  _onSelectAccount = (event) => {
    const accountId = event.target.value;
    const currentAccount = this.state.accounts.find(acct => acct.id === accountId);
    this.setState({currentAccount: currentAccount}, () => {
      this.setState(this._getStateFromStores())
    });
  }

  _onReprocessRules = () => {
    const needsMessageBodies = () => {
      for (const rule of this.state.rules) {
        for (const condition of rule.conditions) {
          if (condition.templateKey === 'body') {
            return true;
          }
        }
      }
      return false;
    }

    if (needsMessageBodies()) {
      NylasEnv.showErrorDialog("One or more of your mail rules requires the bodies of messages being processed. These rules can't be run on your entire mailbox.");
    }

    const task = new ReprocessMailRulesTask(this.state.currentAccount.id)
    Actions.queueTask(task);
  }

  _onAddRule = () => {
    Actions.addMailRule({accountId: this.state.currentAccount.id});
  }

  _onSelectRule = (rule) => {
    this.setState({selectedRule: rule});
  }

  _onReorderRule = (rule, startIdx, endIdx) => {
    Actions.reorderMailRule(rule.id, endIdx);
  }

  _onDeleteRule = (rule) => {
    Actions.deleteMailRule(rule.id);
  }

  _onRuleNameEdited = (newName, rule) => {
    Actions.updateMailRule(rule.id, {name: newName});
  }

  _onRuleConditionModeEdited = (event) => {
    Actions.updateMailRule(this.state.selectedRule.id, {conditionMode: event.target.value});
  }

  _onRuleEnabled = () => {
    Actions.updateMailRule(this.state.selectedRule.id, {disabled: false, disabledReason: null});
  }

  _onRulesChanged = () => {
    const next = this._getStateFromStores();
    const nextRules = next.rules;
    const prevRules = this.state.rules ? this.state.rules : [];

    const added = _.difference(nextRules, prevRules);
    if (added.length === 1) {
      next.selectedRule = added[0];
    }

    this.setState(next);
  }

  _onTasksChanged = () => {
    this.setState({tasks: TaskQueue.findTasks(ReprocessMailRulesTask, {})})
  }

  _renderAccountPicker() {
    const options = this.state.accounts.map(account =>
      <option value={account.id} key={account.id}>{account.label}</option>
    );

    return (
      <select
        value={this.state.currentAccount.id}
        onChange={this._onSelectAccount}
        style={{margin: 0, minWidth: 200}}
      >
        {options}
      </select>
    );
  }

  _renderMailRules() {
    if (this.state.rules.length === 0) {
      return (
        <div className="empty-list">
          <RetinaImg
            className="icon-mail-rules"
            name="rules-big.png"
            mode={RetinaImg.Mode.ContentDark}
          />
          <h2>No rules</h2>
          <button className="btn btn-small" onMouseDown={this._onAddRule}>
            Create a new rule
          </button>
        </div>
      );
    }
    return (
      <Flexbox>
        <EditableList
          showEditIcon
          className="rule-list"
          items={this.state.rules}
          itemContent={this._renderListItemContent}
          onCreateItem={this._onAddRule}
          onReorderItem={this._onReorderRule}
          onDeleteItem={this._onDeleteRule}
          onItemEdited={this._onRuleNameEdited}
          selected={this.state.selectedRule}
          onSelectItem={this._onSelectRule}
        />
        {this._renderDetail()}
      </Flexbox>
    );
  }

  _renderListItemContent(rule) {
    if (rule.disabled) {
      return (<div className="item-rule-disabled">{rule.name}</div>);
    }
    return rule.name;
  }

  _renderDetail() {
    const rule = this.state.selectedRule;

    if (rule) {
      return (
        <ScrollRegion className="rule-detail">
          {this._renderDetailDisabledNotice()}
          <div className="inner">
            <span>If </span>
            <select value={rule.conditionMode} onChange={this._onRuleConditionModeEdited}>
              <option value="any">Any</option>
              <option value="all">All</option>
            </select>
            <span> of the following conditions are met:</span>
            <ScenarioEditor
              instances={rule.conditions}
              templates={this.state.conditionTemplates}
              onChange={(conditions) => Actions.updateMailRule(rule.id, {conditions})}
              className="well well-matchers"
            />
            <span>Perform the following actions:</span>
            <ScenarioEditor
              instances={rule.actions}
              templates={this.state.actionTemplates}
              onChange={(actions) => Actions.updateMailRule(rule.id, {actions})}
              className="well well-actions"
            />
          </div>
        </ScrollRegion>
      );
    }

    return (
      <div className="rule-detail">
        <div className="no-selection">Create a rule or select one to get started</div>
      </div>
    );
  }

  _renderDetailDisabledNotice() {
    if (!this.state.selectedRule.disabled) return false;
    return (
      <div className="disabled-reason">
        <button className="btn" onClick={this._onRuleEnabled}>Enable</button>
        This rule has been disabled. Make sure the actions below are valid
        and re-enable the rule.
        <div>({this.state.selectedRule.disabledReason})</div>
      </div>
    );
  }

  _renderTasks() {
    if (this.state.tasks.length === 0) return false;
    return (
      <div style={{flex: 1, paddingLeft: 20}}>
        {this.state.tasks.map((task) => {
          return (
            <Flexbox style={{alignItems: 'baseline'}}>
              <div style={{paddingRight: "12px"}}>
                <RetinaImg name="sending-spinner.gif" width={18} mode={RetinaImg.Mode.ContentPreserve} />
              </div>
              <div>
                <strong>{AccountStore.accountForId(task.accountId).emailAddress}</strong>
                {` — ${Number(task.numberOfImpactedItems()).toLocaleString()} processed...`}
              </div>
              <div style={{flex: 1}} />
              <button className="btn btn-sm" onClick={() => Actions.cancelTask(task)}>
                Cancel
              </button>
            </Flexbox>
          );
        })}
      </div>
    );
  }

  render() {
    const processDisabled = this.state.tasks.some((task) =>
      task.accountId === this.state.currentAccount.id
    );

    return (
      <div className="container-mail-rules">
        <section>
          <Flexbox className="container-dropdown">
            <div>Account:</div>
            <div className="dropdown">{this._renderAccountPicker()}</div>
          </Flexbox>
          <p>Rules only apply to the selected account.</p>

          {this._renderMailRules()}

          <Flexbox style={{marginTop: 40, maxWidth: 600}}>
            <div>
              <button disabled={processDisabled} className="btn" style={{'float': 'right'}} onClick={this._onReprocessRules}>
                Process entire inbox
              </button>
            </div>
            {this._renderTasks()}
          </Flexbox>

          <p style={{marginTop: 10}}>
            By default, mail rules are only applied to new mail as it arrives.
            Applying rules to your entire inbox may take a long time and
            degrade performance.
          </p>
        </section>
      </div>
    );
  }

}

export default PreferencesMailRules;
