class SwitchAutoComplete {
  /**
   * @param {HTMLElement|string} input
   * @param {HTMLElement|string} panel
   * @param {string[]} switchArray
   * @param {object} opts
   */
  constructor(input, panel, switchArray = [], opts = {}) {
    this.inputEl = typeof input === 'string' ? document.querySelector(input) : input;
    this.panelEl = typeof panel === 'string' ? document.querySelector(panel) : panel;
    if (!this.inputEl || !this.panelEl) throw new Error('Invalid input/panel element');

    this.opts = Object.assign({
      previewOnFocus: true,
      previewCount: 30,
      resultLimit: 1000
    }, opts);

    this.setArray(switchArray);
    this.activeIndex = -1;

    // 이벤트 바인딩
    this.onInput   = this._handleInput.bind(this);
    this.onFocus   = this._handleFocus.bind(this);
    this.onKeydown = this._handleKeydown.bind(this);
    this.onClickOutside = this._handleClickOutside.bind(this);

    this.inputEl.addEventListener('input', this.onInput);
    this.inputEl.addEventListener('focus', this.onFocus);
    this.inputEl.addEventListener('keydown', this.onKeydown);
    document.addEventListener('mousedown', this.onClickOutside);
  }

  destroy() {
    this.inputEl.removeEventListener('input', this.onInput);
    this.inputEl.removeEventListener('focus', this.onFocus);
    this.inputEl.removeEventListener('keydown', this.onKeydown);
    document.removeEventListener('mousedown', this.onClickOutside);
    this.hidePanel();
  }

  setArray(arr) {
    this.switchArray = Array.from(new Set((arr || []).filter(Boolean)));
  }

  _handleInput(e) {
    const q = (e.target.value || '').trim();
    this._filterAndRender(q);
  }

  _handleFocus() {
    if (!this.inputEl.value && this.opts.previewOnFocus) {
      this._renderPanel(this.switchArray.slice(0, this.opts.resultLimit));
      this.showPanel();
    }
  }

  _handleKeydown(e) {
    if (this.panelEl.hidden) return;
    const items = this._items();
    if (!items.length) return;

    if (e.key === 'ArrowDown') { e.preventDefault(); this._move(1); }
    else if (e.key === 'ArrowUp') { e.preventDefault(); this._move(-1); }
    else if (e.key === 'Enter') {
      if (this.activeIndex >= 0) { e.preventDefault(); this._pick(items[this.activeIndex].dataset.value); }
    } else if (e.key === 'Escape') { this.hidePanel(); }
  }

  _handleClickOutside(e) {
    if (!this.inputEl.closest('.ac-wrap')?.contains(e.target)) this.hidePanel();
  }

  _filterAndRender(query) {
    if (!query) {
      this.hidePanel();
      return;
    }
    const q = query.toLowerCase();
    let results = this.switchArray.filter(s => s.toLowerCase().includes(q));
    if (this.opts.resultLimit > 0) results = results.slice(0, this.opts.resultLimit);
    if (results.length) { this._renderPanel(results); this.showPanel(); }
    else { this.hidePanel(); }
  }

  _renderPanel(list) {
    this.panelEl.innerHTML = '';
    this.activeIndex = -1;
    const frag = document.createDocumentFragment();
    list.forEach((sw) => {
      const item = document.createElement('div');
      item.className = 'ac-item';
      item.textContent = sw;
      item.dataset.value = sw;
      item.addEventListener('mousedown', (ev) => { ev.preventDefault(); this._pick(sw); });
      frag.appendChild(item);
    });
    this.panelEl.appendChild(frag);
  }

  _items() { return Array.from(this.panelEl.querySelectorAll('.ac-item')); }

  _move(delta) {
    const items = this._items();
    if (!items.length) return;
    this.activeIndex = (this.activeIndex + delta + items.length) % items.length;
    items.forEach(el => el.classList.remove('active'));
    const el = items[this.activeIndex];
    el.classList.add('active');
    el.scrollIntoView({ block: 'nearest' });
  }

  _pick(value) {
    this.inputEl.value = value;
    this.hidePanel();
  }

  showPanel() { this.panelEl.hidden = false; }
  hidePanel() { this.panelEl.hidden = true; this.activeIndex = -1; }
}

/* switchData(JSON) 읽기 */
function parseEmbeddedJson(id) {
  const el = document.getElementById(id);
  if (!el) return [];
  let txt = el.textContent || '';
  txt = txt
    .replace(/\/\*[\s\S]*?\*\//g, '')
    .replace(/(^|[^:])\/\/.*$/mg, '$1')
    .replace(/,\s*([}\]])/g, '$1');
  try {
    const data = JSON.parse(txt);
    return Array.isArray(data) ? data : [];
  } catch (e) {
    console.error('switchData parse error', e);
    return [];
  }
}

/* 초기화 */
document.addEventListener('DOMContentLoaded', () => {
  const switches = parseEmbeddedJson('switchData');
  const ac = new SwitchAutoComplete('#switchInput', '#switchPanel', switches, {
    previewOnFocus: true,
    resultLimit: 2000
  });
});
