const {
  Observable,
  defer,
  BehaviourSubject,
  pluck,
  of,
  range,
  merge,
  Subject,
} = rxjs;
const {
  flatMap,
  flatMapLatest,
  toArray,
  finalize,
  takeLast,
  findIndex,
  takeUntil,
  defaultIfEmpty,
} = rxjs.operators;
const Layer = ol.layer.Layers;
const { Source } = ol.source;

let submitPress = false;
let isFirstLoaded = false;
let lockerLocations = [];
let numberOfFilteredItems = [];
let districtFilterData = [];
let regionFilterData = [];
let areaFilterData = [];
let reactiveFilterData, reactiveDistrictData, reactiveRegionData, reactiveAreaData;
let filteredDistrict = [];
let filteredRegionName = "";
let filteredDistrictName = "";
let filteredArea = [];
let multiFilterObject = {};

let clickedIndex = 0;
let selectedLocationNameId;
let callBackObject = {};
let dropDownSelectedItemContainer;
let currentSubscription = null;
let virtualScrollInstance = null;
let popup = new ol.Overlay.Popup();
let locDataObservable = getResponse('', _userAuthObject);

function getLocalizedText(textObj) {
  return textObj[_locale] || textObj.en;
}

function isEmptyObject(obj) {
  return !!obj && Object.keys(obj).length === 0 && obj.constructor === Object;
}

function convertRegion(val) {
  if (val === 'Kowloon' || val === '九龍') {
    return 'KOWLOON';
  } else if (val === 'New Territories' || val === '新界' || val === 'Outlying Islands' || val === '離島') {
    return 'NEW TERRITORIES';
  } else {
    return 'HONG KONG';
  }
}

function capitaliseString(str) {
  if (str.includes("_")) {
    const parts = str.split("_");
    const first = parts[0][0].toUpperCase() + parts[0].slice(1).toLowerCase();
    const last = parts[1][0].toUpperCase() + parts[1].slice(1).toLowerCase();
    return `${first} ${last}`;
  } else {
    return str;
  }
}

function isSubset(filterCriteria, locationObj) {
  let matched = true;

  _.forEach(filterCriteria, (value, key) => {
    if (key === "search") {
      if (value) {
        const filterValLowerCase = value.trim().toLowerCase();
        const searchFields = [
          locationObj.province.trim().toLowerCase(),
          translateRegion(locationObj.province.trim().toLowerCase()),
          locationObj.city.trim().toLowerCase(),
          translateDistrict(locationObj.city.trim().toLowerCase()),
          locationObj.district.trim().toLowerCase(),
          translateArea(locationObj.district.trim().toLowerCase()),
          locationObj.locationName.trim().toLowerCase(),
          locationObj.locationId.trim().toLowerCase(),
          locationObj.address1En.trim().toLowerCase(),
          locationObj.address1.trim().toLowerCase(),
        ];

        const foundMatch = searchFields.some(field =>
          field.includes(filterValLowerCase) ||
          stringSimilarity.compareTwoStrings(filterValLowerCase, field) >= 0.9
        );

        if (!foundMatch) {
          matched = false;
          return false;
        }
      }
    } else if (!_.isEqual(value, locationObj[key])) {
      matched = false;
      return false;
    }
  });

  return matched;
}

const closeModalSelection = () => {
  if (isEmptyObject(callBackObject)) {
    return;
  }

  delete multiFilterObject["province"];
  delete multiFilterObject["city"];
  delete multiFilterObject["district"];

  const handleWooCommerceBlocks = (callBackObject) => {
    return new Promise((resolve, reject) => {
      const updateAddress = (addressData) => {
        return new Promise((resolve, reject) => {
          jQuery.ajax({
            url: updateShippingAddressEndpoint,
            type: "POST",
            processData: true,
            headers: {
              "X-WP-Nonce": wp_rest_nonce
            },
            data: {
              shippingAddress1: addressData.address1En,
              shippingAddress2: addressData.address2En,
              locationId: addressData.locationId,
              region: addressData.province,
              district: addressData.district,
              country: addressData.country,
              locationType: addressData.locationType
            },
            success: (data) => resolve(data),
            error: (error) => reject(error)
          });
        });
      };

      showLoadingState();

      updateAddress(callBackObject)
        .then((response) => {
          hideLoadingState();
          closeModal();
          resolve(response);
        })
        .catch((error) => {
          hideLoadingState();
          reject(error);
        });
    });
  };

  // Handle WooCommerce Shortcodes (old logic)
  const handleWooCommerceShortcodes = (callBackObject) => {
    return new Promise((resolve, reject) => {
      const finalAddressLine = lang.includes('zh') ? callBackObject.address1 : callBackObject.address1En;
      const formattedAddress = finalAddressLine.charAt(0) !== "["
        ? `[${callBackObject.locationId}] ${finalAddressLine}`
        : finalAddressLine;

      // Update form fields
      updateShippingFields(formattedAddress, callBackObject);
      updateBillingFields(formattedAddress, callBackObject);

      setTimeout(() => {
        closeModal();
        resolve();
      }, 500);
    });
  };

  // Determine which logic to use based on page type
  if (jQuery('[data-block-name="woocommerce/checkout"], [data-block-name="woocommerce/cart"]').length) {
    callBackObject['useShippingAsBilling'] = getUseShippingAsBilling() ? 'yes' : 'no';
    handleWooCommerceBlocks(callBackObject).then((response) => {
      setShippingAddress(response.data.shipping);
      __internalSetUseShippingAsBilling(response.data.useShippingAsBilling);
      setBillingAddress(response.data.billing);
    });
  } else if (jQuery('.woocommerce-checkout').length) {
    handleWooCommerceShortcodes(callBackObject).then(() => {
      jQuery('.woocommerce-checkout').trigger('update');
    });
  } else if (jQuery('.cart_totals').length) {
    callBackObject['useShippingAsBilling'] = 'yes';
    handleWooCommerceBlocks(callBackObject).then(() => {
      jQuery('.cart_totals').trigger('wc_update_cart');
    });
  }
};

const closeModal = () => {
  delete multiFilterObject["province"];
  delete multiFilterObject["city"];
  delete multiFilterObject["district"];

  const modal = document.getElementById("shipany-woo-plugin-modal");
  modal.classList.remove("shipany-woo-plugin-showModal");
};

function showLoadingState() {
  jQuery(".shipany-woo-plugin-modal .mapLeftWrapper #filterLoader").show();
  jQuery(".shipany-woo-plugin-modal .mapLeftWrapper div.mapFiltersWrapper").hide();
  jQuery(".shipany-woo-plugin-modal .mapLeftWrapper div.containerParentTextDiv").hide();
  jQuery(".shipany-woo-plugin-modal .modalCloseBtn").hide();
  jQuery(".shipany-woo-plugin-modal .modalConfirmBtnWrapper").hide();

  const overlay = jQuery('<div id="overlay" style="background-color: rgba(128, 128, 128, 0.5);position: fixed;inset: 0px;top: 0;bottom: 0;left: 0;right: 0;"></div>');
  const overflow = jQuery("body").css("overflow");
  jQuery("body").append(overlay);
  jQuery("body").css("overflow", "hidden");
}

function hideLoadingState() {
  jQuery(".shipany-woo-plugin-modal .mapLeftWrapper #filterLoader").hide();
  jQuery(".shipany-woo-plugin-modal .mapLeftWrapper div.mapFiltersWrapper").show();
  jQuery(".shipany-woo-plugin-modal .mapLeftWrapper div.containerParentTextDiv").show();
  jQuery(".shipany-woo-plugin-modal .modalCloseBtn").show();
  jQuery(".shipany-woo-plugin-modal .modalConfirmBtnWrapper").show();
  jQuery("#overlay").remove();
  jQuery("body").css("overflow", "visible");
}

function updateShippingFields(addressLine, callBackObject) {
  jQuery('#shipping_country').val(callBackObject.country).trigger('change');

  if (shipany_setting.shipany_locker_length_truncate > 11 && addressLine.length > 11) {
    jQuery('#shipping_address_1').val(addressLine.substring(0, shipany_setting.shipany_locker_length_truncate));
  } else {
    jQuery('#shipping_address_1').val(addressLine);
  }

  jQuery('#shipping_city').val(callBackObject.district);
  jQuery('select#shipping_state.state_select.select2-hidden-accessible').val(convertRegion(callBackObject.province));
  jQuery('span#select2-shipping_state-container.select2-selection__rendered').text(callBackObject.province);
  jQuery('input#shipping_state').val(callBackObject.province);

  if (region_idx == 2) {
    jQuery('#shipping_postcode').val('000000');
  }
}

function updateBillingFields(addressLine, callBackObject) {
  if (shipany_setting.shipany_bypass_billing_address == 'no' || shipany_setting.shipany_bypass_billing_address == null) {
    jQuery('#billing_country').val(callBackObject.country).trigger('change');

    if (shipany_setting.shipany_locker_length_truncate > 11 && addressLine.length > 11) {
      jQuery('#billing_address_1').val(addressLine.substring(0, shipany_setting.shipany_locker_length_truncate));
    } else {
      jQuery('#billing_address_1').val(addressLine);
    }

    jQuery('#billing_city').val(callBackObject.district);
    jQuery('select#billing_state.state_select.select2-hidden-accessible').val(convertRegion(callBackObject.province));
    jQuery('span#select2-billing_state-container.select2-selection__rendered').text(callBackObject.province);
    jQuery('input#billing_state').val(callBackObject.province);

    if (region_idx == 2) {
      jQuery('#billing_postcode').val('000000');
    }
  } else {
    if (jQuery('#ship-to-different-address-checkbox').get(0) && !jQuery('#ship-to-different-address-checkbox').get(0).checked) {
      jQuery('#ship-to-different-address-checkbox').click();
    }
  }
}

function initializeModalUI() {
  const modal = document.getElementById("shipany-woo-plugin-modal");

  const topBar = document.createElement("div");
  topBar.className = "modalTopBar";

  const closeBtn = document.createElement("span");
  Object.assign(closeBtn, {
    className: "modalCloseBtn",
    onclick: closeModal,
    innerHTML: "✕",
  });

  topBar.appendChild(closeBtn);
  modal.insertBefore(topBar, modal.firstChild);

  const modalConfirmBtnWrapper = document.createElement("div");
  modalConfirmBtnWrapper.className = "modalConfirmBtnWrapper";

  const modalConfirmBtn = document.createElement("button");
  Object.assign(modalConfirmBtn, {
    className: "modalConfirmBtn",
    innerHTML: getLocalizedText({
      en: "Confirm",
      zh: "確定",
    }),
    onclick: closeModalSelection,
  });

  modalConfirmBtnWrapper.appendChild(modalConfirmBtn);
  modal.appendChild(modalConfirmBtnWrapper);

  const modalPowerBy = document.createElement("div");
  Object.assign(modalPowerBy, {
    className: "copyright-text",
    innerHTML: "Powered by <a href='https://www.shipany.io' target='_blank' rel='noopener noreferrer' style='color:#15669d'>ShipAny</a>"
  });
  modal.appendChild(modalPowerBy);
}

function initializeContainer() {
  // Create main container
  const containerDiv = document.createElement("div");
  containerDiv.className = "containerDiv";
  document.getElementById("mapWrapper").appendChild(containerDiv);

  const leftWrapper = document.createElement("div");
  leftWrapper.className = "mapLeftWrapper";

  const filtersWrapper = document.createElement("div");
  filtersWrapper.className = "mapFiltersWrapper";

  const districtFilter = document.createElement("SELECT");
  districtFilter.className = "districtFilter mapFilter";

  const regionFilter = document.createElement("SELECT");
  regionFilter.className = "regionFilter mapFilter";

  const areaFilter = document.createElement("SELECT");
  areaFilter.className = "areaFilter mapFilter";

  leftWrapper.appendChild(filtersWrapper);

  const containerParentDiv = document.createElement("div");
  containerParentDiv.className = "containerParentTextDiv";
  if (_withSearchBar) {
    initializeSearchBar(leftWrapper);
  }

  return {
    containerDiv,
    leftWrapper,
    filtersWrapper,
    districtFilter,
    regionFilter,
    areaFilter,
    containerParentDiv
  };
}

function initializeSearchBar(leftWrapper) {
  const searchBarWrapper = document.createElement("div");
  searchBarWrapper.className = "mapFiltersWrapper";

  const searchBar = document.createElement("input");
  searchBar.id = "shipanySearchBar";
  searchBar.className = "shipanySearchBar mapFilter";
  searchBar.placeholder = getLocalizedText({
    en: "Search by location name, address, or location ID",
    zh: "搜尋地點名稱、地址或地點編號",
  });
  searchBar.style.width = "100%";

  searchBarWrapper.appendChild(searchBar);
  leftWrapper.appendChild(searchBarWrapper);

  return searchBar;
}

function processLocationData(result) {
  const lat = result.latitude;
  const long = result.longitude;
  const coordinates = ol.proj.fromLonLat([long, lat]);
  const locationItem = {
    address1: `[${result.code}] ${result.addr.lns_cht[0]}`,
    address1En: `[${result.code}] ${result.addr.lns[0]}`,
    address2: `[${result.code}] ${result.addr.lns_cht[1]}`,
    address2En: `[${result.code}] ${result.addr.lns[1]}`,
    city: result.addr[region_idx == 2 ? 'distr' : 'state'],
    country: getCountryCode(result.addr.cnty),
    district: result.addr.distr,
    province: result.addr[region_idx == 2 ? 'city' : 'reg'],
    latitude: lat,
    longitude: long,
    locationEn: result.name,
    locationId: result.code,
    locationName: getLocalizedText({
      zh: result.name_cht,
      en: result.name,
    }),
    locationType: capitaliseString(result.typ),
    operatingTime: result.open_hours,
    operatingTimeCN: result.open_hours_cht,
    geometry: new ol.geom.Point(coordinates)
  };

  numberOfFilteredItems.push(locationItem);

  const feature = new ol.Feature({
    type: "click",
    ...locationItem
  });

  lockerLocations.push(feature);

  // Update filter data
  updateFilterData(locationItem);
}

function getCountryCode(countryCode) {
  const countryMapping = {
    'TWN': 'TW',
    'HKG': 'HK',
    'MAC': 'MO',
  };
  return countryMapping[countryCode] || countryCode;
}

function updateFilterData(locationItem) {
  districtFilterData.push(locationItem.city);
  regionFilterData.push(locationItem.province);
  areaFilterData.push(locationItem.district);
}

function multiFilterList(filterCriteria) {
  return reactiveList.pipe(
    filter((locationObject) => {
      const matchFound = isSubset(filterCriteria, locationObject.values_);
      if (matchFound) {
        filteredDistrict.push(locationObject.values_.city);
        filteredArea.push(locationObject.values_.district);
        return true;
      }
      return false;
    }),
    defaultIfEmpty(undefined)
  );
}

function setupFilterObservables() {
  const filterByRegionParams$ = fromEvent([regionFilter], "change").pipe(
    map(($event) => {
      const selectElement = $event.target;
      const selectedOption = selectElement.options[selectElement.selectedIndex];
      return selectedOption.innerHTML;
    }),
    debounceTime(1000),
    distinctUntilChanged(),
    filter((value) => value.length > 1)
  );

  const filterByDistrictParams$ = fromEvent([districtFilter], "change").pipe(
    map(($event) => {
      const selectElement = $event.target;
      const selectedOption = selectElement.options[selectElement.selectedIndex];
      return selectedOption.innerHTML;
    }),
    debounceTime(1000),
    distinctUntilChanged(),
    filter((value) => value.length > 1)
  );

  const filterByAreaParams$ = fromEvent([areaFilter], "change").pipe(
    map(($event) => {
      const selectElement = $event.target;
      const selectedOption = selectElement.options[selectElement.selectedIndex];
      return selectedOption.innerHTML;
    }),
    debounceTime(1000),
    distinctUntilChanged(),
    filter((value) => value.length > 1)
  );

  // const filterBySearchBarParams$ = fromEvent([searchBar], "keyup").pipe(
  //   map((e) => {
  //     return e.target.value;
  //   }),
  //   debounceTime(1000),
  //   // distinctUntilChanged(),
  // );

  return {
    filterByRegionParams$,
    filterByDistrictParams$,
    filterByAreaParams$
  };
}

function handleRegionFilter(selectedRegion) {
  resetFilterState();

  if (selectedRegion !== "All Regions" && selectedRegion !== "全部區域") {
    multiFilterObject["province"] = selectedRegion;
    delete multiFilterObject["city"];
    delete multiFilterObject["district"];
    filteredRegionName = selectedRegion;
  } else {
    delete multiFilterObject["province"];
    delete multiFilterObject["city"];
    delete multiFilterObject["district"];
    filteredRegionName = "All Regions";
  }

  return multiFilterObject;
}

function handleDistrictFilter(selectedDistrict) {
  resetFilterState();

  if (selectedDistrict !== "All Districts" && selectedDistrict !== "全部地區") {
    multiFilterObject["city"] = selectedDistrict;
    filteredDistrictName = selectedDistrict;
    delete multiFilterObject["district"];
  } else {
    filteredDistrictName = selectedDistrict;
    delete multiFilterObject["city"];
    delete multiFilterObject["district"];
  }

  return multiFilterObject;
}

function handleAreaFilter(selectedArea) {
  resetFilterState();

  if (selectedArea !== "All Areas" && selectedArea !== "全部範圍") {
    multiFilterObject["district"] = selectedArea;
  } else {
    delete multiFilterObject["district"];
  }

  return multiFilterObject;
}

function resetFilterState() {
  filteredDistrict = [];
  filteredArea = [];
  clickedIndex = 0;
  hidePopUp();
  numberOfFilteredItems = [];

  if (virtualScrollInstance) {
    virtualScrollInstance.updateData([]);
  } else {
    containerParentDiv.innerHTML = "";
  }
}

function subscribeMultiFilter() {
  if (currentSubscription) {
    currentSubscription.unsubscribe();
  }

  const completeSubject$ = new Subject();
  let resultTimeout = null;

  const { filterByRegionParams$, filterByDistrictParams$, filterByAreaParams$ } = setupFilterObservables();

  const multiFilter = merge(
    filterByRegionParams$.pipe(map(handleRegionFilter)),
    filterByDistrictParams$.pipe(map(handleDistrictFilter)),
    filterByAreaParams$.pipe(map(handleAreaFilter))
  ).pipe(
    flatMap(multiFilterList),
    takeUntil(completeSubject$)
  );

  currentSubscription = multiFilter.subscribe({
    next: (result) => {
      if (resultTimeout) {
        clearTimeout(resultTimeout);
      }

      if (result === null) {
        showNoResultsMessage();
      } else {
        updateList(result.values_);
      }

      resultTimeout = setTimeout(() => {
        completeSubject$.next(true);
      }, 500);
    },

    complete: () => {
      updateListDom(numberOfFilteredItems);
      hideLoadingState();
      updateFilterDropdowns();
      setTimeout(() => subscribeMultiFilter(), 100);
      virtualScrollInstance.reload();
    },

    error: (err) => {
      console.error("Filter subscription error:", err);
      setTimeout(() => subscribeMultiFilter(), 1000);
    }
  });
}

function showNoResultsMessage() {
  const noResultText = document.createElement("p");
  noResultText.setAttribute("style", "text-align: center");
  noResultText.innerHTML = getLocalizedText({
    en: "The location you have searched for does not have any Shipany Locations available",
    zh: "你搜尋的地方沒有任何智能櫃服務",
  });
  containerParentDiv.appendChild(noResultText);
}

function updateFilterDropdowns() {
  filteredDistrict = Array.from(new Set(filteredDistrict));
  filteredArea = Array.from(new Set(filteredArea));

  const districtFilterElement = document.getElementsByClassName("districtFilter")[0];
  const areaFilterElement = document.getElementsByClassName("areaFilter")[0];

  if (filteredRegionName === "") {
    if (filteredDistrictName !== "") {
      updateAreaDropdown(areaFilterElement);
    }
  } else {
    updateDistrictDropdown(districtFilterElement);
    updateAreaDropdown(areaFilterElement);
  }

  updateSelectedOptions(districtFilterElement, areaFilterElement);
}

function updateDistrictDropdown(districtFilterElement) {
  removeOptions(districtFilterElement);
  filteredDistrict.forEach(district => {
    const option = document.createElement("option");
    option.text = district;
    if (_locale === "zh") {
      option.label = translateDistrict(option.label);
    }
    districtFilterElement.add(option);
  });
}

function updateAreaDropdown(areaFilterElement) {
  removeOptions(areaFilterElement);
  filteredArea.forEach(area => {
    const option = document.createElement("option");
    option.text = area;
    if (_locale === "zh") {
      option.label = translateArea(option.label);
    }
    areaFilterElement.add(option);
  });
}

function updateSelectedOptions(districtFilterElement, areaFilterElement) {
  const cityName = multiFilterObject["city"];
  const districtName = multiFilterObject["district"];

  // Set district selection
  if (cityName === undefined) {
    districtFilterElement.options.selectedIndex = 1;
  } else {
    for (let i = 0; i < districtFilterElement.options.length; i++) {
      if (districtFilterElement.options[i].text === cityName) {
        districtFilterElement.options.selectedIndex = i;
        break;
      }
    }
  }

  if (districtName === undefined) {
    areaFilterElement.options.selectedIndex = 1;
  } else {
    for (let i = 0; i < areaFilterElement.options.length; i++) {
      if (areaFilterElement.options[i].text === districtName) {
        areaFilterElement.options.selectedIndex = i;
        break;
      }
    }
  }
}

function removeOptions(selectElement) {
  for (let i = selectElement.options.length - 1; i >= 2; i--) {
    selectElement.remove(i);
  }
}

function updateList(result) {
  numberOfFilteredItems.push(result);
}

function updateListDom(results) {
  if (typeof VirtualScroll === 'undefined') {
    setTimeout(() => updateListDom(results), 100);
    return;
  }

  if (!virtualScrollInstance) {
    initializeVirtualScroll();
  }

  if (results.length > 0) {
    showVirtualScrollLoading();
  }

  virtualScrollInstance.updateData(results);

  setTimeout(() => {
    hideVirtualScrollLoading();
  }, 200);
}

function showVirtualScrollLoading() {
  if (containerParentDiv) {
    containerParentDiv.style.opacity = '0.7';
    containerParentDiv.style.pointerEvents = 'none';
  }
}

function hideVirtualScrollLoading() {
  if (containerParentDiv) {
    containerParentDiv.style.opacity = '1';
    containerParentDiv.style.pointerEvents = 'auto';
  }
}

function initializeVirtualScroll() {
  const modalHeight = window.innerHeight * 0.8;
  const reservedSpace = 200;
  const containerHeight = Math.min(400, modalHeight - reservedSpace);

  containerParentDiv.style.height = `${containerHeight}px`;
  containerParentDiv.style.maxHeight = `${containerHeight}px`;
  containerParentDiv.style.overflow = 'auto';

  virtualScrollInstance = new VirtualScroll({
    container: containerParentDiv,
    defaultItemHeight: 85,
    containerHeight: containerHeight,
    renderItem: renderLocationItem,
    data: numberOfFilteredItems,
    overscan: 3
  });

  containerParentDiv.addEventListener('itemSelect', handleVirtualScrollSelection);
}

function renderLocationItem(result, index) {
  const listItem = createLocationListItem(result, index);
  return listItem;
}

function handleVirtualScrollSelection(event) {
  const { item, index, element } = event.detail;

  hidePopUp();
  callBackObject = item;
  showPopUp(callBackObject);
  updateSelectedItemStyling(element);
}

function createLocationListItem(result, index) {
  const containerTextDiv = document.createElement("div");
  containerTextDiv.className = "containerChildTextDiv";
  containerTextDiv.style.padding = "12px";
  containerTextDiv.style.cursor = "pointer";
  containerTextDiv.style.transition = "background-color 0.2s ease";

  const locationContainer = document.createElement("INPUT");
  Object.assign(locationContainer, {
    type: "radio",
    name: "list",
    id: result.locationId,
    className: "mapRadioBtn",
    style: "margin-right: 12px",
    checked: result.selected ?? false
  });

  const locationContentDiv = document.createElement("label");
  Object.assign(locationContentDiv, {
    htmlFor: result.locationId,
    className: "shipany-label",
    style: "display: flex; align-items: flex-start; cursor: pointer; width: 100%"
  });

  const locationContentText = document.createElement("div");
  locationContentText.style.flex = "1";

  if (result.locationName || result.locationId) {
    const locationName = createLocationNameElement(result);
    locationName.innerHTML = locationName.innerHTML;
    locationContentText.appendChild(locationName);
  }

  if (result.operatingTime) {
    const operatingTime = createOperatingTimeElement(result);
    locationContentText.appendChild(operatingTime);
  }

  const address = createAddressElement(result);
  locationContentText.appendChild(address);

  const city = createCityElement(result);
  locationContentText.appendChild(city);

  const locationType = createLocationTypeElement(result);
  locationContentText.appendChild(locationType);

  locationContentDiv.appendChild(locationContentText);
  containerTextDiv.appendChild(locationContainer);
  containerTextDiv.appendChild(locationContentDiv);

  return containerTextDiv;
}

function updateSelectedItemStyling(element, index) {
  const previousSelected = containerParentDiv.querySelector('.selected');
  if (previousSelected) {
    previousSelected.classList.remove('selected');
  }

  element.classList.add('selected');

  const radioBtn = element.querySelector('.mapRadioBtn');
  const addressElement = element.querySelector('.contentAddress');
  const operatingTimeElement = element.querySelector('.operatingTime');
  const locationTypeElement = element.querySelector('.contentLocationType');
  const cityElement = element.querySelector('.contentCity');

  if (radioBtn) radioBtn.checked = true;
  if (addressElement) addressElement.classList.add('display-block');
  if (operatingTimeElement) operatingTimeElement.classList.add('display-block');
  if (locationTypeElement) locationTypeElement.classList.add('display-block');
  if (cityElement) cityElement.classList.add('display-none');
}

function createLocationNameElement(result) {
  const locationName = document.createElement("P");
  locationName.setAttribute("class", "locationName");

  const displayName = (result?.locationName ?? "").replace(result.locationId, '');

  if (result.locationType === "Convenience Store" || result.typ === "Petrol Station") {
    locationName.innerHTML = getLocalizedText({
      en: `${result.locationId} - ${displayName}${result.address1En}`,
      zh: `${result.locationId} - ${displayName}${result.address1}`,
    });
  } else {
    locationName.innerHTML = getLocalizedText({
      en: `${result.locationId} - ${displayName}`,
      zh: `${result.locationId} - ${displayName}`,
    });
  }

  return locationName;
}

function createOperatingTimeElement(result) {
  const operatingTime = document.createElement("P");
  operatingTime.setAttribute("class", "operatingTime");
  operatingTime.innerHTML = getLocalizedText({
    en: result?.operatingTime ?? "",
    zh: result?.operatingTimeCN ?? "",
  });
  return operatingTime;
}

function createAddressElement(result) {
  const address = document.createElement("P");
  address.innerHTML = getLocalizedText({
    en: result?.address1En ?? "",
    zh: result?.address1 ?? "",
  });
  address.setAttribute("class", "contentAddress");
  return address;
}

function createCityElement(result) {
  const city = document.createElement("P");

  if (result.locationType) {
    Object.assign(city, {
      innerHTML: getLocalizedText({
        en: `${capitaliseString(result.locationType)} | ${result?.city ?? ""}`,
        zh: `${translateType(capitaliseString(result.locationType))} | ${translateDistrict(result?.city ?? "")}`,
      }),
      className: "contentCity",
    });
  } else {
    Object.assign(city, {
      innerHTML: result.city,
      className: "contentCity",
    });
  }

  return city;
}

function createLocationTypeElement(result) {
  const locationType = document.createElement("P");

  if (result.locationType) {
    Object.assign(locationType, {
      innerHTML: getLocalizedText({
        en: capitaliseString(result.locationType),
        zh: translateType(capitaliseString(result.locationType)),
      }),
      className: "contentLocationType",
    });
  }

  return locationType;
}


function setFocus(itemIndex) {
  const textDivs = document.getElementsByClassName("containerChildTextDiv");

  Object.keys(textDivs).forEach((key) => {
    const textDiv = textDivs[key];
    textDiv.classList.remove("selected-background");

    const cityElement = textDiv.getElementsByClassName("contentCity")[0];
    const addressElement = textDiv.getElementsByClassName("contentAddress")[0];
    const operatingTimeElement = textDiv.getElementsByClassName("operatingTime")[0];

    if (cityElement) cityElement.classList.remove("display-none");
    if (addressElement) addressElement.classList.remove("display-block");
    if (operatingTimeElement) operatingTimeElement.classList.remove("display-block");
  });

  const selectedDiv = textDivs[itemIndex];
  const radioBtn = selectedDiv.getElementsByClassName("mapRadioBtn")[0];
  const cityElement = selectedDiv.getElementsByClassName("contentCity")[0];
  const addressElement = selectedDiv.getElementsByClassName("contentAddress")[0];
  const operatingTimeElement = selectedDiv.getElementsByClassName("operatingTime")[0];

  radioBtn.checked = true;
  selectedDiv.classList.add("selected-background");
  addressElement.classList.add("display-block");

  if (operatingTimeElement) {
    operatingTimeElement.classList.add("display-block");
  }

  cityElement.classList.add("display-none");
  radioBtn.focus();
}

function setupListClickHandler() {
  if (!virtualScrollInstance) {
    const onListClick$ = fromEvent(containerParentDiv, "click").pipe(
      map((event) => {
        hidePopUp();
        clearCurrentSelection();

        if (event.srcElement.classList.contains('containerChildTextDiv')) {
          event.srcElement.getElementsByClassName("mapRadioBtn")[0].click();
          return;
        }

        const parentContainer = event.srcElement.parentNode.closest(".containerChildTextDiv");
        if (parentContainer) {
          handleLocationSelection(event.srcElement, parentContainer);
        }

        return null;
      })
    );

    onListClick$.subscribe();
  }
}

function clearCurrentSelection() {
  const currentSelectedElements = document.getElementsByClassName('selected-background');

  for (let i = 0; i < currentSelectedElements.length; i++) {
    const element = currentSelectedElements[i];
    if (!element) continue;

    const cityElement = element.getElementsByClassName("contentCity")[0];
    const addressElement = element.getElementsByClassName("contentAddress")[0];
    const locationTypeElement = element.getElementsByClassName("contentLocationType")[0];
    const operatingTimeElement = element.getElementsByClassName("operatingTime")[0];

    if (cityElement) cityElement.classList.remove("display-none");
    if (addressElement) addressElement.classList.remove("display-block");
    if (locationTypeElement) locationTypeElement.classList.remove("display-block");
    if (operatingTimeElement) operatingTimeElement.classList.remove("display-block");

    element.classList.remove('selected-background');
  }
}

function handleLocationSelection(clickedElement, parentContainer) {
  const locationNameElement = clickedElement.parentNode.getElementsByClassName("locationName")[0];
  const selectedLocationId = locationNameElement.innerHTML.split(" - ")[0];
  const selectedItemIndex = numberOfFilteredItems.findIndex(
    item => item.locationId === selectedLocationId
  );

  callBackObject = numberOfFilteredItems[selectedItemIndex];
  showPopUp(callBackObject);

  parentContainer.classList.add("selected-background");

  const addressElement = clickedElement.parentNode.getElementsByClassName("contentAddress")[0];
  const operatingTimeElement = clickedElement.parentNode.getElementsByClassName("operatingTime")[0];
  const locationTypeElement = clickedElement.parentNode.getElementsByClassName("contentLocationType")[0];
  const cityElement = clickedElement.parentNode.getElementsByClassName("contentCity")[0];

  addressElement.classList.add("display-block");
  if (operatingTimeElement) operatingTimeElement.classList.add("display-block");
  locationTypeElement.classList.add("display-block");
  cityElement.classList.add("display-none");
}

const hidePopUp = () => {
  popup.hide();
  popup.setOffset([0, 0]);
};

const showPopUp = (result) => {
  const coordinates = ol.proj.fromLonLat([result.longitude, result.latitude]);
  const location = getLocalizedText({
    en: result?.locationEn ?? "",
    zh: result?.locationName ?? "",
  });
  const address = getLocalizedText({
    en: result?.address1En ?? "",
    zh: result?.address1 ?? "",
  });
  const operatingTime = getLocalizedText({
    en: result?.operatingTime ?? "",
    zh: result?.operatingTimeCN ?? "",
  });

  const popupContent = `
    <div style="width:220px; margin-top:3px">${result?.locationId ?? ""}</div>
    <div style="width:220px; margin-top:3px">${capitaliseString(result?.locationType ?? "")} | ${result?.district ?? ""}</div>
    <div style="width:220px; margin-top:3px">${location}</div>
    <div style="width:220px; margin-top:3px; color: grey">${address}</div>
    <div style="width:220px; margin-top:3px; color: grey">${operatingTime}</div>
    <div style="width:220px; margin-top:3px; color: grey">${result?.city ?? ""}</div>
  `;

  popup.setOffset([0, -32]);
  popup.show(coordinates, popupContent);
};

function initializeComponents() {
  initializeModalUI();
  const containerComponents = initializeContainer();
  window.containerParentDiv = containerComponents.containerParentDiv;
  window.districtFilter = containerComponents.districtFilter;
  window.regionFilter = containerComponents.regionFilter;
  window.areaFilter = containerComponents.areaFilter;

  startDataLoading(containerComponents);
}

function startDataLoading(containerComponents) {
  // console.log("0" + " " + new Date().getTime());

  const reactiveList = from(lockerLocations);
  window.reactiveList = reactiveList;

  locDataObservable.subscribe({
    next: (result) => {
      processLocationData(result);

      if (!isFirstLoaded) {
        containerComponents.leftWrapper.appendChild(containerComponents.containerParentDiv);

        const loader = document.createElement("div");
        loader.className = "loader";
        loader.id = "filterLoader";
        loader.style.display = "none";
        containerComponents.leftWrapper.appendChild(loader);

        containerComponents.containerDiv.appendChild(containerComponents.leftWrapper);
        isFirstLoaded = true;
      }
    },

    complete: () => {
      completeDataLoading(containerComponents);
    },

    error: (error) => {
      console.error("Data loading error:", error);
    }
  });
}

function completeDataLoading(containerComponents) {
  updateListDom(numberOfFilteredItems);
  document.getElementById("mapWrapper").appendChild(containerComponents.containerDiv);

  districtFilterData = Array.from(new Set(districtFilterData));
  regionFilterData = Array.from(new Set(regionFilterData));
  areaFilterData = Array.from(new Set(areaFilterData));

  setupRegionFilter(containerComponents.regionFilter, containerComponents.filtersWrapper);
  setupDistrictFilter(containerComponents.districtFilter, containerComponents.filtersWrapper);
  setupAreaFilter(containerComponents.areaFilter, containerComponents.filtersWrapper);
  setupListClickHandler();
  subscribeMultiFilter();
  document.getElementById("loader").style.display = "none";
}

function setupRegionFilter(regionFilter, filtersWrapper) {
  reactiveRegionData = from(regionFilterData).subscribe({
    next: (result) => {
      if (result !== '') {
        const regionFilterItem = document.createElement("option");
        regionFilterItem.innerHTML = result;
        regionFilterItem.label = getLocalizedText({
          en: regionFilterItem.label,
          zh: translateRegion(regionFilterItem.label),
        });
        regionFilter.appendChild(regionFilterItem);
      }
    },

    complete: () => {
      addDefaultOption(regionFilter, {
        en: "Region",
        zh: "區域",
      });

      const regionFilterTitle = document.createElement("p");
      regionFilterTitle.innerHTML = getLocalizedText({
        en: _filterCriteria === null ? "2. Select Region" : "1. Select Region",
        zh: "1. 選擇區域",
      });
      regionFilterTitle.className = "regionFilterTitle";

      filtersWrapper.appendChild(regionFilterTitle);
      filtersWrapper.appendChild(regionFilter);
    }
  });
}

function setupDistrictFilter(districtFilter, filtersWrapper) {
  reactiveDistrictData = from(districtFilterData).subscribe({
    next: (result) => {
      if (result !== "") {
        const districtFilterItem = document.createElement("option");
        districtFilterItem.innerHTML = result;
        if (_locale === "zh") {
          districtFilterItem.label = translateDistrict(districtFilterItem.label);
        }
        districtFilter.appendChild(districtFilterItem);
      }
    },

    complete: () => {
      addDefaultOption(districtFilter, {
        en: "District",
        zh: "地區",
      });

      const districtFilterTitle = document.createElement("p");
      districtFilterTitle.innerHTML = getLocalizedText({
        en: _filterCriteria === null ? "3. Select District" : "2. Select District",
        zh: "2. 選擇地區",
      });
      districtFilterTitle.className = "districtFilterTitle";

      filtersWrapper.appendChild(districtFilterTitle);
      filtersWrapper.appendChild(districtFilter);
    }
  });
}

function setupAreaFilter(areaFilter, filtersWrapper) {
  reactiveAreaData = from(areaFilterData).subscribe({
    next: (result) => {
      if (result !== '') {
        const areaFilterItem = document.createElement("option");
        areaFilterItem.innerHTML = result;
        if (_locale === "zh") {
          areaFilterItem.label = translateArea(areaFilterItem.label);
        }
        areaFilter.appendChild(areaFilterItem);
      }
    },

    complete: () => {
      addDefaultOption(areaFilter, {
        en: "Area",
        zh: "範圍",
      });

      const areaFilterTitle = document.createElement("p");
      areaFilterTitle.innerHTML = getLocalizedText({
        en: _filterCriteria === null ? "4. Select Area" : "3. Select Area",
        zh: "3. 選擇範圍",
      });
      areaFilterTitle.className = "areaFilterTitle";

      filtersWrapper.appendChild(areaFilterTitle);
      filtersWrapper.appendChild(areaFilter);
    }
  });
}

function addDefaultOption(selectElement, textObj) {
  const dropDownSelectionEmpty = document.createElement("OPTION");
  Object.assign(dropDownSelectionEmpty, {
    disabled: true,
    selected: true,
  });
  dropDownSelectionEmpty.innerHTML = getLocalizedText(textObj);

  const firstChild = selectElement.firstChild;
  if (firstChild && (
    firstChild.innerHTML === "All Regions" ||
    firstChild.innerHTML === "全部區域" ||
    firstChild.innerHTML === "區域" ||
    firstChild.innerHTML === "All Districts" ||
    firstChild.innerHTML === "全部地區" ||
    firstChild.innerHTML === "地區" ||
    firstChild.innerHTML === "All Areas" ||
    firstChild.innerHTML === "全部範圍" ||
    firstChild.innerHTML === "範圍"
  )) {
    selectElement.insertBefore(dropDownSelectionEmpty, firstChild);
  }
}

initializeComponents();