/**
 * @module module/query-sk
 * @description <h2><code>query-sk</code></h2>
 *
 * Starting from a serialized paramtools.ParamSet, this control allows the user
 * to build up a query, suitable for passing to query.New.
 *
 * @evt query-change - The 'query-sk' element will produce 'query-change' events when the query
 *      parameters chosen have changed. The event contains the current selections formatted as a URL query, found in e.detail.q.
 *
 * @evt query-change-delayed - The same exact event as query-change, but with a 500ms delay after
 *      the query stops changing.
 *
 * @attr {string} current_query - The current query formatted as a URL formatted query string.
 * @attr {boolean} hide_invert - If the option to invert a query should be made available to
 *       the user.
 * @attr {boolean} hide_regex - If the option to include regex in the query should be made
 *       available to the user.
 */
import { define } from 'elements-sk/define';
import { html } from 'lit-html';
import { ParamSet, toParamSet, fromParamSet } from 'common-sk/modules/query';
import { SelectSk } from 'elements-sk/select-sk/select-sk';
import { ElementSk } from '../ElementSk';
import {
  QueryValuesSk,
  QueryValuesSkQueryValuesChangedEventDetail,
} from '../query-values-sk/query-values-sk';

import '../query-values-sk';
import 'elements-sk/select-sk';
import 'elements-sk/styles/buttons';

// The delay in ms before sending a delayed query-change event.
const DELAY_MS = 500;

export interface QuerySkQueryChangeEventDetail {
  readonly q: string;
}

/**
 * Removes the prefix, if any, from a query value.
 *
 * TODO(jcgregorio) - The fact that query values can have a prefix of either '!' or '~'
 * is just something you have to know about them. We need a way to share the knowledge
 * of all possible valid prefixes with the Go code.
 */
export const removePrefix = (s: string): string => {
  if (s.length == 0) {
    return s;
  }
  if ('~!'.includes(s[0])) {
    return s.slice(1);
  }
  return s;
};

export class QuerySk extends ElementSk {
  private static template = (ele: QuerySk) => html`
    <div class="filtering">
      <input
        id="fast"
        @input=${ele._fastFilter}
        placeholder="Filter Parameters and Values"
      />
      ${QuerySk.clearFilterButton(ele)}
    </div>
    <div class="bottom">
      <div class="selection">
        <select-sk @selection-changed=${ele._keyChange}>
          ${QuerySk.keysTemplate(ele)}
        </select-sk>
        <button @click=${ele._clear} class="clear_selections">
          Clear Selections
        </button>
      </div>
      <query-values-sk
        id="values"
        class=${ele._keySelect?.selection === -1 ? 'hidden' : ''}
        @query-values-changed=${ele._valuesChanged}
        ?hide_invert=${ele.hide_invert}
        ?hide_regex=${ele.hide_regex}
      ></query-values-sk>
    </div>
  `;

  private static clearFilterButton(ele: QuerySk) {
    if (!ele._filtering) {
      return html``;
    }
    return html`
      <button
        @click=${ele._clearFilter}
        class="clear_filters"
        title="Clear filter"
      >
        &cross;
      </button>
    `;
  }

  private static keysTemplate = (ele: QuerySk) => ele._keys.map(
    (k) => html`
          <div>${k}</div>
        `,
  );

  private _paramset: ParamSet = {};

  private _originalParamset: ParamSet = {};

  // True if there is text in the fitler input.
  private _filtering: boolean = false;

  // We keep the current_query as an object.
  private _query: ParamSet = {};

  private _key_order: string[] = [];

  // The full set of keys in the desired order.
  private _keys: string[] = [];

  // The id of a pending timeout func that will send a delayed query-change event.
  private _delayedTimeout: number | null = null;

  private _keySelect: SelectSk | null = null;

  private _values: QueryValuesSk | null = null;

  private _fast: HTMLInputElement | null = null;

  constructor() {
    super(QuerySk.template);
  }

  connectedCallback() {
    super.connectedCallback();
    this._upgradeProperty('paramset');
    this._upgradeProperty('key_order');
    this._upgradeProperty('current_query');
    this._upgradeProperty('hide_invert');
    this._upgradeProperty('hide_regex');
    this._render();
    this._values = this.querySelector('#values');
    this._keySelect = this.querySelector('select-sk');
    this._fast = this.querySelector('#fast');
  }

  private _valuesChanged(
    e: CustomEvent<QueryValuesSkQueryValuesChangedEventDetail>,
  ) {
    const key = this._keys[this._keySelect!.selection as number];
    if (this._fast!.value.trim() !== '') {
      // Things get complicated if the user has entered a filter. The user may
      // have selections in this._query[key] which don't appear in e.detail
      // because they have been filtered out, so we should only add/remove
      // values from this._query[key] that appear in this._paramset[key], while
      // being careful because value(s) may be prefixed with either a '!' or a
      // '~' if they are invert or regex queries.

      // When we toggle from a regex to a non-regex we need to clear the values.
      if (
        !e.detail.regex
        && this._query[key]
        && this._query[key][0][0] === '~'
      ) {
        this._query[key] = [];
      }

      if (e.detail.regex) {
        this._query[key] = e.detail.values;
      }

      // The user might have toggled the invert checkbox, which means we need to
      // make sure that the current values for the current key are also inverted
      // appropriately even if not displayed due to the filter.
      this._applyInvert(key, e.detail.invert);

      // Make everything into Sets to make our lives easier.
      const valuesDisplayed = new Set(this._paramset[key]);
      const currentQueryForKey = new Set(this._query[key]);
      const unprefixedSelectionsFromEvent = new Set(
        e.detail.values.map(removePrefix),
      );

      // Loop over valuesDisplayed, if the value appears in selectionsFromEvent
      // then add it to currentQueryForKey, otherwise remove it from
      // currentQueryForKey.
      valuesDisplayed.forEach((value) => {
        const prefix = e.detail.invert ? '!' : '';
        const prefixedValue = prefix + value;
        if (unprefixedSelectionsFromEvent.has(value)) {
          currentQueryForKey.add(prefixedValue);
        } else {
          currentQueryForKey.delete(prefixedValue);
        }
      });
      this._query[key] = [...currentQueryForKey];
    } else {
      this._query[key] = e.detail.values;
    }
    this._queryChanged();
  }

  /**
   * Set or clear the invery prefix ('!') on all the values for the given key in
   * this._query, based on the value of 'invert'.
   */
  private _applyInvert(key: string, invert: boolean) {
    const values = this._query[key];
    if (!values || !values.length) {
      return;
    }
    const valuesHaveInvert = values[0][0] === '!';
    if (invert === valuesHaveInvert) {
      // eslint-disable-next-line no-useless-return
      return;
    } if (invert && !valuesHaveInvert) {
      this._query[key] = values.map((v) => `!${v}`);
    } else {
      this._query[key] = values.map(removePrefix);
    }
  }

  private _keyChange() {
    if (this._keySelect!.selection === -1) {
      return;
    }
    const key = this._keys[this._keySelect!.selection as number];
    this._values!.options = this._paramset[key] || [];
    this._values!.selected = this._query[key] || [];
    this._render();
  }

  private _recalcKeys() {
    const keys = Object.keys(this._paramset);
    keys.sort();
    // Pull out all the keys that appear in _key_order to be pushed to the front of the list.
    const pre = this._key_order.filter((ordered) => keys.indexOf(ordered) > -1);
    const post = keys.filter((key) => pre.indexOf(key) === -1);
    this._keys = pre.concat(post);
  }

  private _queryChanged() {
    const prev_query = this.current_query;
    this._rationalizeQuery();
    if (prev_query !== this.current_query) {
      this.dispatchEvent(
        new CustomEvent<QuerySkQueryChangeEventDetail>('query-change', {
          detail: { q: this.current_query },
          bubbles: true,
        }),
      );
      window.clearTimeout(this._delayedTimeout!);
      this._delayedTimeout = window.setTimeout(() => {
        this.dispatchEvent(
          new CustomEvent<QuerySkQueryChangeEventDetail>(
            'query-change-delayed',
            {
              detail: { q: this.current_query },
              bubbles: true,
            },
          ),
        );
      }, DELAY_MS);
    }
  }

  // Rationalize the _query, i.e. remove keys and values that don't exist in the ParamSet.
  private _rationalizeQuery() {
    // We will use this to determine whether we've made any changes to the original query.
    const originalCurrentQuery = this.current_query;

    const originalKeys = Object.keys(this._originalParamset);
    Object.keys(this._query).forEach((key) => {
      if (originalKeys.indexOf(key) === -1) {
        // Filter out invalid keys.
        delete this._query[key];
      } else {
        // Filter out invalid values.
        this._query[key] = this._query[key].filter(
          (val) => this._originalParamset[key].includes(val)
            || val.startsWith('~')
            || val.startsWith('!'),
        );
      }
    });

    // _rationalizeQuery is called when current_query is set. This avoids an infinite recursion.
    const newCurrentQuery = fromParamSet(this._query);
    if (newCurrentQuery !== originalCurrentQuery) {
      this.current_query = fromParamSet(this._query);
    }
  }

  private _clear() {
    this._query = {};
    this._recalcKeys();
    this._queryChanged();
    this._keyChange();
    this._render();
  }

  private _fastFilter() {
    const filterString = this._fast!.value.trim();
    const filters = filterString.toLowerCase().split(/\s+/);

    if (filterString) {
      this._filtering = true;
    }

    // Create a closure that returns true if the given label matches the filter.
    const matches = (s: string) => {
      s = s.toLowerCase();
      return filters.filter((f) => s.indexOf(f) > -1).length > 0;
    };

    // Loop over this._originalParamset.
    const filtered: ParamSet = {};
    Object.keys(this._originalParamset).forEach((paramkey) => {
      // If the param key matches, then all the values go over.
      if (matches(paramkey)) {
        filtered[paramkey] = this._originalParamset[paramkey];
      } else {
        // Look for matches in the param values.
        const valueMatches: string[] = [];
        this._originalParamset[paramkey].forEach((paramvalue) => {
          if (matches(paramvalue)) {
            valueMatches.push(paramvalue);
          }
        });
        if (valueMatches.length > 0) {
          filtered[paramkey] = valueMatches;
        }
      }
    });

    this._paramset = filtered;
    this._recalcKeys();
    this._keyChange();
    this._render();
  }

  private _clearFilter() {
    this._fast!.value = '';
    this.paramset = this._originalParamset;
    this._filtering = false;
    this._queryChanged();
    this._render();
  }

  /** @prop paramset {Object} A serialized paramtools.ParamSet. */
  get paramset() {
    return this._paramset;
  }

  set paramset(val) {
    // Record the current key so we can restore it later.
    let prevSelectKey = '';
    if (this._keySelect && this._keySelect.selection) {
      prevSelectKey = this._keys[this._keySelect!.selection as number];
    }

    this._paramset = val;
    this._originalParamset = val;
    this._recalcKeys();
    if (this._fast && this._fast.value.trim() !== '') {
      this._fastFilter();
    }
    this._render();

    // Now re-select the current key if it still exists post-filtering.
    if (
      this._keySelect
      && prevSelectKey
      && this._keys.indexOf(prevSelectKey) !== -1
    ) {
      this._keySelect.selection = this._keys.indexOf(prevSelectKey);
      this._keyChange();
    }
  }

  /**
   * The keys in the order they should appear. All keys not in the key order will be present after
   * and in alphabetical order.
   */
  get key_order() {
    return this._key_order;
  }

  set key_order(val) {
    this._key_order = val;
    this._recalcKeys();
    this._render();
  }

  /** Mirrors the hide_invert attribute.  */
  get hide_invert() {
    return this.hasAttribute('hide_invert');
  }

  set hide_invert(val) {
    if (val) {
      this.setAttribute('hide_invert', '');
    } else {
      this.removeAttribute('hide_invert');
    }
    this._render();
  }

  /**  Mirrors the hide_regex attribute.  */
  get hide_regex() {
    return this.hasAttribute('hide_regex');
  }

  set hide_regex(val) {
    if (val) {
      this.setAttribute('hide_regex', '');
    } else {
      this.removeAttribute('hide_regex');
    }
    this._render();
  }

  /** Mirrors the current_query attribute.  */
  get current_query() {
    return this.getAttribute('current_query') || '';
  }

  set current_query(val: string) {
    this.setAttribute('current_query', val);
  }

  static get observedAttributes() {
    return ['current_query', 'hide_invert', 'hide_regex'];
  }

  attributeChangedCallback(name: string, _: string, newValue: string) {
    if (name === 'current_query') {
      // Convert the current_query string into an object.
      this._query = toParamSet(newValue);

      // Remove invalid key/value pairs from the new query.
      this._rationalizeQuery();

      // This updates query-value-sk with the new selection and renders the template.
      if (this._connected) {
        this._keyChange();
      }
    } else {
      this._render();
    }
  }
}

define('query-sk', QuerySk);
