import './add-language-dialog';

import {css, html, LitElement} from 'lit';
import {customElement, property} from 'lit/decorators.js';
import {map} from 'lit/directives/map.js';

import {isoLangs} from '../../../common/consts';
import {msg} from '../../../common/i18n';
import {TargetLangs} from '../../../common/options';
import {SHARED_STYLES} from '../../shared/shared-styles';

@customElement('languages-editor')
export default class LanguagesEditor extends LitElement {
  @property({type: Object}) languages: TargetLangs;

  static get styles() {
    return [
      SHARED_STYLES,
      css`
        #languages_container {
          width: 300px;
          height: 250px;
          border: 1px solid #ccc;
          background-color: #fafafa;
          overflow: auto;
        }

        #languages {
          list-style: none;
          margin: 0;
          padding: 0;
        }

        #languages li {
          display: flex;
          flex-direction: row;
          align-items: center;
          padding: 15px;
          border-bottom: 1px dashed #ddd;
          background-color: white;
          -webkit-user-select: none;
        }

        #languages li .label {
          flex-grow: 1;
        }

        #languages li .delete {
          font-size: 18px;
          color: red;
          padding-left: 2px;
          margin-left: 2px;
        }

        #languages li .movebtn {
          font-size: 16px;
          color: blue;
          padding: 0 2px;
          margin: 0 2px;
        }

        #languages li :is(.delete, .movebtn) {
          cursor: pointer;
          text-align: center;
        }

        #languages li .movebtn--disabled {
          color: gray;
          cursor: not-allowed;
        }

        #languages_footer {
          width: 300px;
          height: 35px;
          background-color: #fff;
          border: 1px solid #ccc;
          border-top: 0;
        }

        #languages_add {
          margin-inline-start: 4px;
          margin-top: 4px;
        }
      `,
    ];
  }

  render() {
    const languageCodes = Object.values(this.languages ?? {});
    const languageList = map(languageCodes, (lang, i) => {
      const moveBtns = [];
      if (i != 0) {
        moveBtns.push(html`
          <button
              class="notbtn movebtn"
              @click=${() => this.swapLanguages(i, i - 1)}>
            ↑
          </button>
        `);
      } else {
        moveBtns.push(html`
          <button class="notbtn movebtn movebtn--disabled">
            ↑
          </button>
        `);
      }
      if (i != languageCodes.length - 1) {
        moveBtns.push(html`
          <button
              class="notbtn movebtn"
              @click=${() => this.swapLanguages(i, i + 1)}>
            ↓
          </button>
        `);
      } else {
        moveBtns.push(html`
          <button class="notbtn movebtn movebtn--disabled">
            ↓
          </button>
        `);
      }

      return html`
        <li data-id=${lang}>
          <span class="label">
            ${isoLangs?.[lang]?.['name']} (${isoLangs?.[lang]?.nativeName})
          </span>
          ${moveBtns}
          <button
              class="notbtn delete"
              @click=${() => this.deleteLanguage(lang)}>
            ×
          </button>
        </li>
      `;
    });

    return html`
      <div id="languages_container">
        <ul id="languages">${languageList}</ul>
      </div>
      <div id="languages_footer">
        <button @click=${this.showAddLanguageDialog} id="languages_add">
          ${msg('options_addlanguage_addbutton')}
        </button>
      </div>

      <add-language-dialog .languages=${this.languages}></add-language-dialog>
    `;
  }

  showAddLanguageDialog() {
    const e = new CustomEvent(
        'show-add-language-dialog', {bubbles: true, composed: true});
    this.renderRoot.querySelector('add-language-dialog').dispatchEvent(e);
  }

  save(languageCodes: string[]) {
    const translateinto = Object.assign({}, languageCodes);
    chrome.storage.sync.set({translateinto});
  }

  deleteLanguage(deleteLang: string) {
    const languageCodes =
        Object.values(this.languages ?? {}).filter(lang => lang != deleteLang);
    this.save(languageCodes);
  }

  swapLanguages(i: number, j: number) {
    const languageCodes = Object.values(this.languages ?? {});
    if (i >= languageCodes.length || j >= languageCodes.length || i < 0 ||
        j < 0) {
      console.error(
          'Can\'t swap languages because the indexes are out of the range.');
      return;
    }
    const tmp = languageCodes[j];
    languageCodes[j] = languageCodes[i];
    languageCodes[i] = tmp;
    this.save(languageCodes);
  }
}
