/* eslint-disable */
/**
 * OpenCulturas Map Module Block JavaScript
 */
(function (Drupal, once) {

  Drupal.OpenCulturasMapBlock = class {
    constructor(mapBlockElement, callback) {
      if (!mapBlockElement) {
        throw "mapBlockElement needed!"
      }
      if (!callback && typeof callback !== "function") {
        throw "callback function needed!"
      }
      this._mapBlockElement = mapBlockElement;
      this._callback = callback;
      this._init();
    }

    _init() {
      this._mapInstance = new Drupal.OpenCulturasMapLeaflet(this._mapBlockElement);
      this._mapInstance.mapElement.addEventListener("newcoords", this._callback.bind(this));
      this._callback();
      this._reloadInteraction = false;
    }

    _initFilter() {
      if (!this._filterElement) return;
      this._filterElement.addEventListener(`submit`, function (event) {
        event.preventDefault();
        this._filter = {};
        const inputElements = this._filterElement.querySelectorAll("input[type='text'], select, input[type='checkbox'], input[type='date']");
        for (const inputElement of inputElements) {
          if (event.submitter && event.submitter.id && event.submitter.id.startsWith("edit-reset") && inputElement) {
            inputElement.value = '';
            if (inputElement.checked && inputElement.checked === true) {
              inputElement.value = '';
              inputElement.checked = false;
            }
            if (inputElement.type === 'select-one') {
              for (const option of inputElement.options) {
                if (option.value.toLowerCase() === 'all') {
                  option.selected = true;
                }
              }
            }
          }

          if (inputElement && inputElement.type === 'checkbox') {
            inputElement.value = (inputElement.checked) ? 1 : '';
          }

          if (inputElement && inputElement.value) {

            if (inputElement.multiple && inputElement.selectedOptions) {
              this._filter[inputElement.name] = [];
              for (const selectedOption of inputElement.selectedOptions) {
                if (selectedOption.value) {
                  this._filter[inputElement.name].push(selectedOption.value);
                }
              }
            } else {
              this._filter[inputElement.name] = inputElement.value;
            }


          }

          if (inputElement.classList.contains('slimselect')) {
            inputElement.dispatchEvent(new CustomEvent('change'))
          }
        }
        this._callback(event);
      }.bind(this));
    }

    get filterElement() {
      return this._filterElement;
    }

    set filterElement(filterElement) {
      if (!filterElement) return;
      this._filterElement = filterElement;
      this._initFilter();
    }

    withFilter(filterElement) {
      this.filterElement = filterElement;
      return this;
    }

    get mapBlockElement() {
      return this._mapBlockElement;
    }

    set mapBlockElement(mapBlockElement) {
      throw "mapBlockElement can only be set on init";
    }

    get mapInstance() {
      return this._mapInstance;
    }

    set mapInstance(mapInstance) {
      throw "mapInstance cannot be set";
    }
  }

  Drupal.behaviors.OpenCulturasMapBlock = {
    mapSelector: '.block-openculturas-map .openculturas-map',
    formValues: [],
    // Drupal base function, runs when the behaviour is attached
    attach: function (context, settings) {
      once('init-openculturas-map-block', this.mapSelector, context).forEach((openculturasMapElement) => {
        let currentFetchOperation = {isActive: false};
        const openCulturasMapBlock = new Drupal.OpenCulturasMapBlock(openculturasMapElement, function (event) {
          const originUrlParams = new URLSearchParams(window.location.search);
          const originUrlParamEntries = originUrlParams.entries();
          const mapType = openculturasMapElement.dataset.type;

          const mapInstance = this.mapInstance;
          const settings = this.mapInstance.settings;

          const locationsClient = new Drupal.OpenCulturasMapLocationsClient();
          const datesClient = new Drupal.OpenCulturasMapDatesClient();

          let client;
          if (settings.get('type') === 'locations') {
            client = locationsClient;
          } else if (settings.get('type') === 'dates') {
            client = datesClient;
          } else {
            throw "No client found for type " + settings.get('type');
          }

          let fetchNew = true;
          if (!event || (event && event.type !== 'newcoords')) {
            // Without Map Move
          } else {
            if (event.detail.distances.pixels < 80 && event.detail.oldCoords.zoom === event.detail.zoom) {
              fetchNew = false;
            }
          }

          if (
            mapInstance
            && mapInstance.radius[mapInstance.zoom.map]
            && mapInstance.coords.map.lat
            && mapInstance.coords.map.lng
            && mapInstance.coords.map.lng >= -180 && mapInstance.coords.map.lng <= 180
          ) {
            client
              .addToQuery("proximity[value]", String(mapInstance.radius[mapInstance.zoom.map]))
              .addToQuery("proximity[origin][lat]", String(mapInstance.coords.map.lat))
              .addToQuery("proximity[origin][lon]", String(mapInstance.coords.map.lng))
          }

          if (this._filter) {
            for (const [filterKey, filterValue] of Object.entries(this._filter)) {
              client.addToQuery(filterKey, filterValue);
            }
            if (event && event.type === 'submit' && event.submitter.id.startsWith("edit-reset")) {
              this.mapInstance.clear();
            } else if (JSON.stringify(this._filter) !== JSON.stringify(this._renderedFilter)) {
              mapInstance.trackOldFilter(this._renderedFilter);
              mapInstance.trackNewFilter(this._filter);
              this.mapInstance.clear();
              this._renderedFilter = this._filter;
            }

            mapInstance.untrackFilters();
          }
          else if(originUrlParamEntries) {
            for(const [originUrlParamEntryKey, originUrlParamEntryValue] of originUrlParamEntries) {
              if(client.getQueryParam(originUrlParamEntryKey)) {
                if(!Array.isArray(client.getQueryParam(originUrlParamEntryKey))) {
                  client.addToQuery(originUrlParamEntryKey, [client.getQueryParam(originUrlParamEntryKey)]);
                }
                client.addToQuery(originUrlParamEntryKey, [originUrlParamEntryValue, ...client.getQueryParam(originUrlParamEntryKey)])
              } else {
                client.addToQuery(originUrlParamEntryKey, originUrlParamEntryValue);
              }
            }
          }
          if (fetchNew) {
            // abort last fetch operation
            currentFetchOperation.isActive = false;

            // start new fetch operation
            currentFetchOperation = {isActive: true};
            const mapEntryPage = client.asyncPagedMapEntries(0);
            const operation = currentFetchOperation;

            mapInstance.setResultCounterBusy(
              (!mapInstance.isWaiting() || !mapInstance.isDirty())
            );

            function processNextMapEntryPage(result) {
              if (!result.done && operation.isActive) {
                mapInstance.setResultCounterBusy(
                  (!mapInstance.isWaiting() || !mapInstance.isDirty())
                );
                mapInstance.withEntryCollection(client._collection).render();
                mapInstance._renderPagedResults();
                mapEntryPage.next().then(processNextMapEntryPage.bind(this));
              }

              if (result.done || !operation.isActive) {
                mapInstance.waitForInteraction();
                mapInstance.setResultCounterBusy(false);
              }

              if(result.done && result.value[0] === 0) {

                if((this._filter && JSON.stringify(this._filter) !== '{}' && JSON.stringify(this._filter) !== '{"a11y_features":"All"}')) {
                  mapInstance._clearResults();
                  mapInstance.counterElement.innerText = Drupal.t('No results');
                } else {
                  if(Object.keys(mapInstance._getRenderedMarkers()).length === 0) {
                    mapInstance.counterElement.innerText = Drupal.t('No results');
                  }
                }

              }
            }

            mapEntryPage.next().then(processNextMapEntryPage.bind(this));
          }

        }).withFilter(openculturasMapElement.querySelector('form'));
      });
    },
  }

}(Drupal, once));
