class FSStateMapNavState {
  code;
  name;
}

class FSStateMapNav {
  mapSourcePath = "themes/custom/fsrd/assets/html/statemapnav.min.html";
  selectID = "fsrd-statemapnav__select";
  mapID = "fsrd-statemapnav__map";

  // Element pointers
  element;
  select;
  map;
  mapTitle;

  // Settings
  targetURLPattern = null;
  newTab = false;
  bordered = false;
  disabledStates = [];
  hiddenStates = [];

  // State Info
  states = new Map();

  constructor(element) {
    this.element = element;
    this.load();
  }

  //#region Event Handlers

  handleSelectChange = (event) => {
    let stateCode = this.select.value;
    if (stateCode.length > 0) {
      this.navigateTo(stateCode);
    }
  };

  handleMapClick = (event) => {
    let stateCode = event.srcElement.getAttribute("data-state");
    if (!this.isDisabled(stateCode)) {
      this.navigateTo(stateCode);
    }
  };

  handleMapMouseEnter = (event) => {
    let stateCode = event.srcElement.getAttribute("data-state");
    let state = this.states.get(stateCode);
    this.mapTitle.innerHTML = state.name;
  };

  handleMapMouseLeave = (event) => {
    this.mapTitle.innerHTML = "";
  };
  //#endregion

  //#region Load

  load() {
    this.loadAttributes();
    this.embedComponent();
  }

  loadAttributes() {
    // Target URL pattern
    if (this.element.hasAttribute("data-url")) {
      this.targetURLPattern = this.element.getAttribute("data-url");
    }

    // Open target in new tab
    if (this.element.hasAttribute("data-newtab")) {
      this.newTab = true;
    }

    // Show border on element.
    if (this.element.hasAttribute("data-bordered")) {
      this.bordered = true;
    }

    // Disabled states
    if (this.element.hasAttribute("data-disabled")) {
      let disabledString = this.element.getAttribute("data-disabled").toUpperCase();
      let states = disabledString.split(",");
      states.forEach((state) => {
        this.disabledStates.push(state.trim());
      });
    }

    // Hidden states
    if (this.element.hasAttribute("data-hidden")) {
      let hiddenString = this.element.getAttribute("data-hidden").toUpperCase();
      let states = hiddenString.split(",");
      states.forEach((state) => {
        this.hiddenStates.push(state.trim());
      });
    }
  }

  loadStates() {
    for (let i = 0; i < this.select.options.length; i++) {
      let option = this.select.options[i];
      if (option.value.length > 0) {
        let state = new FSStateMapNavState();
        state.code = option.value;
        state.name = option.innerText;
        this.states.set(state.code, state);
      }
    }
  }

  setDisabled() {
    let states = this.map.querySelectorAll("path, circle");
    states.forEach((state) => {
      let stateCode = state.getAttribute("data-state");
      if (this.isDisabled(stateCode)) {
        state.classList.add("disabled");
      }
    });

    for (let i = 0; i < this.select.options.length; i++) {
      let option = this.select.options[i];
      if (this.isDisabled(option.value)) {
        option.disabled = true;
      }
    }
  }

  setHidden() {
    let states = this.map.querySelectorAll("path, circle");
    states.forEach((state) => {
      let stateCode = state.getAttribute("data-state");
      if (this.isHidden(stateCode)) {
        state.classList.add("hidden");
      }
    });

    for (let i = 0; i < this.select.options.length; i++) {
      let option = this.select.options[i];
      if (this.isHidden(option.value)) {
        option.hidden = true;
      }
    }
  }

  embedComponent() {
    fetch(this.getMapSourceURL()).then((response) => {
      response.text().then((text) => {
        this.element.innerHTML = text;
        if (this.bordered) {
          this.element.classList.add("bordered");
        }
        this.select = document.getElementById(this.selectID);
        this.select.title = "Select a State";
        this.map = document.getElementById(this.mapID);
        this.mapTitle = this.map.querySelector("title");

        this.select.addEventListener("change", this.handleSelectChange);
        let states = this.map.querySelectorAll("path, circle");
        states.forEach((state) => {
          state.addEventListener("click", this.handleMapClick);
          state.addEventListener("mouseenter", this.handleMapMouseEnter);
          state.addEventListener("mouseleave", this.handleMapMouseLeave);
        });
        this.setDisabled();
        this.setHidden();
        this.loadStates();
      });
    });
  }

  //#endregion

  getMapSourceURL() {
    return `${drupalSettings.path.baseUrl}${this.mapSourcePath}`;
  }

  isDisabled(stateCode) {
    if (this.disabledStates == null) {
      return false;
    } else {
      return this.disabledStates.includes(stateCode);
    }
  }

  isHidden(stateCode) {
    if (this.hiddenStates == null) {
      return false;
    } else {
      return this.hiddenStates.includes(stateCode);
    }
  }

  navigateTo(stateCode) {
    let targetURL = "";

    stateCode = stateCode.toLowerCase();

    if (this.targetURLPattern == null) {
      targetURL = `${window.location.origin}${window.location.pathname}/${stateCode}`;
    } else {
      targetURL = this.targetURLPattern;
      if (targetURL.includes("{state_code}")) {
        targetURL = targetURL.replace("{state_code}", stateCode);
      } else {
        targetURL = targetURL + stateCode;
      }
    }
    if (this.newTab) {
      window.open(targetURL, "_blank");
    } else {
      window.location.assign(targetURL);
    }
  }
}

Drupal.behaviors.fsStateMapNav = {
  attach: function (context, settings) {
    once("fsStateMapNav", ".fsrd-statemapnav", context).forEach(function (
      element
    ) {
      let mapNav = new FSStateMapNav(element);
    });
  },
};