class RessourceList {
  /* A wrapper class for the list.js list.
   * This class is not meant to be used directly, instead it should be used as
   * a base class for concrete ressource list implementations.
   */

  static autoInit() {
    CorpusList.autoInit();
    CorpusFileList.autoInit();
    JobList.autoInit();
    JobInputList.autoInit();
    JobResultList.autoInit();
    PublicCorporaList.autoInit();
    PublicUserList.autoInit();
    SpaCyNLPPipelineModelList.autoInit();
    TesseractOCRPipelineModelList.autoInit();
    UserList.autoInit();
  }

  static options = {page: 5, pagination: {innerWindow: 4, outerWindow: 1}};

  constructor(listElement, options = {}) {
    if (!(listElement.hasAttribute('id'))) {
      let i;
      for (i = 0; true; i++) {
        if (document.querySelector(`#ressource-list-${i}`)) {continue;}
        listElement.id = `ressource-list-${i}`;
        break;
      }
    }
    options = {
      ...{pagination: {item: `<li><a class="page" href="#${listElement.id}"></a></li>`}},
      ...options
    }
    if ('ressourceMapper' in options && typeof options.ressourceMapper === 'function') {
      this.ressourceMapper = options.ressourceMapper;
      delete options.ressourceMapper;
    }
    if ('initialHtmlGenerator' in options && typeof options.initialHtmlGenerator === 'function') {
      this.initialHtmlGenerator = options.initialHtmlGenerator;
      listElement.innerHTML = this.initialHtmlGenerator(listElement.id);
      delete options.initialHtmlGenerator;
    }
    if ('sortArgs' in options) {
      this.sortArgs = options.sortArgs;
      delete options.sortArgs;
    }
    this.listjs = new List(listElement, {...RessourceList.options, ...options});
    this.listjs.list.innerHTML = `
      <tr>
        <td class="row" colspan="100%">
          <div class="col s12">&nbsp;</div>
          <div class="col s3 m2 xl1">
            <div class="preloader-wrapper active">
              <div class="spinner-layer spinner-green-only">
                <div class="circle-clipper left">
                  <div class="circle"></div>
                </div>
                <div class="gap-patch">
                  <div class="circle"></div>
                </div>
                <div class="circle-clipper right">
                  <div class="circle"></div>
                </div>
              </div>
            </div>
          </div>
          <div class="col s9 m6 xl5">
            <span class="card-title">Waiting for data...</span>
            <p>This list is not initialized yet.</p>
          </div>
        </td>
      </tr>
    `.trim();
    this.userId = this.listjs.listContainer.dataset.userId;
    this.listjs.list.addEventListener('click', (event) => {this.onClick(event)});
    this.isInitialized = false;
    if (this.userId) {
      app.subscribeUser(this.userId)
        .then((response) => {
          app.socket.on('PATCH', (patch) => {
            if (this.isInitialized) {this.onPatch(patch);}
          });
        });
      app.getUser(this.userId)
        .then((user) => {
          this.init(user);
          this.isInitialized = true;
        });
    }
  }

  _init(ressources) {
    this.listjs.clear();
    this.add(Object.values(ressources));
    this.listjs.list.insertAdjacentHTML(
      'afterbegin',
      `
        <tr class="show-if-only-child">
          <td colspan="100%">
            <span class="card-title"><i class="left material-icons" style="font-size: inherit;">file_download</i>Nothing here...</span>
            <p>No ressource available.</p>
          </td>
        </tr>
      `.trim()
    );
  }

  init(user) {throw 'Not implemented';}

  onClick(event) {throw 'Not implemented';}

  onPatch(patch) {throw 'Not implemented';}

  add(ressources) {
    let values = Array.isArray(ressources) ? ressources : [ressources];
    if ('ressourceMapper' in this) {
      values = values.map((value) => {return this.ressourceMapper(value);});
    }
    this.listjs.add(values, () => {
      if ('sortArgs' in this) {
        this.listjs.sort(...this.sortArgs);
      }
    });
  }

  remove(id) {
    this.listjs.remove('id', id);
  }

  replace(id, valueName, newValue) {
    this.listjs.get('id', id)[0].values({[valueName]: newValue});
  }
}
