import * as $ from "jquery";
import { InobyModule } from "@lib/inoby-module";
import { WPBSPostLinkQueryObject } from "./search.d";
import { includes } from "../webpack.entry";

class WpbsSearch extends InobyModule {
  private maximumCapacityFilterEnabled: boolean = false;
  private filterCapacity: number = null;

  run() {
    let enabled = $(".wpbs-enable-search-posts").length > 0;
    this.maximumCapacityFilterEnabled = $(".wpbs-enable-maximum-capacity-filter").length > 0;
    if (enabled) {
      let $wpbs = $(".wpbs_s-search-widget").parent()[0];
      let observer = this.formObserver();
      observer.observe($wpbs, { childList: true });
      this.hideResultPopup();
      this.updateSearch();

      if (this.maximumCapacityFilterEnabled) {
        this.addCapacityListener();
      }
    }
  }

  formObserver() {
    return new MutationObserver((mutations) => {
      mutations.forEach((_) => {
        this.hideResultPopup();
        this.updateSearch();
      });
    });
  }

  updatePostLinks() {
    const startDateStr = $("input[name='wpbs-search-start-date']").val().toString();
    const endDateStr = $("input[name='wpbs-search-end-date']").val().toString();

    const queryObject: WPBSPostLinkQueryObject = {};

    if (startDateStr.length) {
      const startDate = new Date(startDateStr);
      queryObject["wpbs-start-year"] = startDate.getFullYear();
      queryObject["wpbs-start-month"] = startDate.getMonth() + 1; // Jan == 0
      queryObject["wpbs-selection-start"] = startDateStr;
    }

    if (endDateStr.length) {
      queryObject["wpbs-selection-end"] = endDateStr;
    }

    if (this.maximumCapacityFilterEnabled && this.filterCapacity !== null) {
      queryObject["wpbs-capacity"] = this.filterCapacity;
    }

    if (!Object.keys(queryObject).length) {
      return;
    }

    const queryString =
      "?" +
      Object.keys(queryObject)
        .map((key) => key + "=" + (queryObject as any)[key])
        .join("&");

    $("[wpbs-post-id]").map((_, div) => {
      // get post link
      const postLinkEl = $(div).find("a");

      // modify href
      let postLink = postLinkEl.attr("href");
      postLink = postLink.split("?")[0] + queryString;

      // add modified href to link
      postLinkEl.attr("href", postLink);
    });
  }

  updateSearch() {
    if (this.maximumCapacityFilterEnabled && $(".wpbs_s-search-widget .wpbs_s-search-widget-field.capacity").length === 0) {
      this.addMaximumCapacityInput();
    }

    this.updatePostLinks();

    //show labels if selected
    $(".wpbs_s-search-widget-field").each(function () {
      const value = $(this).find("input[type='text'], input[type='number']").first().val();

      if (value && value.toString().length > 0) {
        $(this).find("label").addClass("show-inplace");
      }
    });

    let $results = $(".wpbs_s-search-widget-results");
    let $noResults = $(".wpbs_s-search-widget-no-results");

    if ($results.length || $noResults.length) {
      let shown: number[] = [];
      $results.children("input.wpbs-post-id").map((_, input) => {
        shown.push(Number.parseInt($(input).val().toString()));
      });

      $("[wpbs-post-id]").map((_, div) => {
        let post_id = Number.parseInt($(div).attr("wpbs-post-id"));

        if (post_id > 0) {
          $(div).removeClass().addClass("masonry-item");

          if (shown.find((val) => val == post_id)) {
            if (!this.checkCapacity(div)) {
              $(div).addClass("booking-exceeded-capacity");
            } else {
              $(div).addClass("booking-avaliable");
            }
          } else {
            $(div).addClass("booking-not-avaliable");
          }
        }
      });
    } else {
      $("[wpbs-post-id]").map((_, div) => {
        $(div).addClass("booking-avaliable");
      });
    }
  }

  hideResultPopup() {
    $(".wpbs_s-search-widget-results").hide();
  }

  checkCapacity(div: HTMLElement) {
    if (this.maximumCapacityFilterEnabled) {
      const accommodationCapacity = Number.parseInt($(div).attr("wpbs-maximum-capacity"));
      if (accommodationCapacity < this.filterCapacity) {
        return false;
      }
    }
    return true;
  }

  getCapacityFromQueryString() {
    const params = new URLSearchParams(window.location.search);
    const capacityStr = params.get("wpbs-capacity");
    if (capacityStr?.length) {
      return Number.parseInt(capacityStr);
    }

    return null;
  }

  addMaximumCapacityInput() {
    // TODO: Translate label and placeholder on backend
    const tpl = `<div class="wpbs_s-search-widget-field capacity">
        <label for="wpbs_s-search-widget-capacity">Počet osôb</label>
        <input type="number" step="1" min="1" placeholder="Počet osôb" id="wpbs_s-search-widget-capacity" class="wpbs_s-search-widget-capacity" name="capacity" size="6">
     </div>`;

    $(".wpbs_s-search-widget-field:nth-child(2)").after(tpl);

    this.filterCapacity = this.getCapacityFromQueryString();

    if (this.filterCapacity !== null) {
      $("input#wpbs_s-search-widget-capacity").val(this.filterCapacity);
    }
  }

  addCapacityListener() {
    $(".search-wrapper").on("change", "#wpbs_s-search-widget-capacity", (e) => {
      const value = $(e.target).val().toString();
      this.filterCapacity = value.length ? Number.parseInt(value) : null;

      // change old value
      let url = window.location.href.replace(/(\?|&)(wpbs-capacity)=(\d+)/s, this.filterCapacity === null ? "" : `$1$2=${this.filterCapacity}`);

      // if wpbs-capacity was deleted and it was first query param
      // change prefix of new first param from & to ?
      if (!url.includes("?") && url.includes("&")) {
        url = url.replace("&", "?");
      }

      // create query param if not exists
      if (this.filterCapacity && !url.includes("wpbs-capacity")) {
        url = url + (url.includes("?") ? "&" : "?") + "wpbs-capacity=" + this.filterCapacity;
      }

      history.replaceState({}, null, url);
    });
  }
}

new WpbsSearch().runOnReady();
