class Schick {
  constructor(selector, options = {}) {
    this.element = document.querySelector(selector);
    this.blocks = options.blocks || [];
    this.blockTypes = options.blockTypes || this.blocks.map(() => 'numeric');
    this.separator = options.separator ?? ' ';
    this.prefix = options.prefix ?? '';
    this.suffix = options.suffix ?? '';
    this.totalLength = this.blocks.reduce((a, b) => a + b, 0);

    this.init();
  }

  onKeyDown(e) {
    if (e.key !== 'Backspace') return;

    const el = this.element;
    const cursorPos = el.selectionStart;
    const val = el.value;

    // Prefix schützen
    if (this.prefix && cursorPos <= this.prefix.length) {
      e.preventDefault();
      return;
    }

    const before = val.slice(0, cursorPos);
    const after = val.slice(el.selectionEnd);

    const sep = this.separator;

    // Zeichen vor Cursor prüfen
    const prevChar = before.slice(-1);

    // 1) Separator vor Cursor entfernen
    if (prevChar === sep) {
      const newBefore = before.slice(0, -1);
      el.value = newBefore + after;
      e.preventDefault();
      this.onInput();
      el.setSelectionRange(newBefore.length, newBefore.length);
      return;
    }

    // 2) Suffix + davorliegendes Zeichen entfernen, wenn Cursor hinter Suffix steht
    if (this.suffix) {
      const suffixLen = this.suffix.length;
      // Cursor steht am Ende und Wert endet mit Suffix?
      if (cursorPos === val.length && val.endsWith(this.suffix)) {
        // Prüfen, ob genügend Zeichen vor Suffix zum Entfernen da sind
        if (val.length > suffixLen) {
          // Entferne Suffix + 1 Zeichen davor
          const newValue = val.slice(0, val.length - suffixLen - 1);
          el.value = newValue;
          e.preventDefault();
          this.onInput();
          el.setSelectionRange(newValue.length, newValue.length);
          return;
        }
      }
    }
  }
  init() {
    this.element.addEventListener('input', this.onInput.bind(this));
    this.element.addEventListener('keydown', this.onKeyDown.bind(this));
  }

  onInput() {
    let val = this.element.value;

    // Prefix entfernen für interne Verarbeitung
    if (this.prefix && val.startsWith(this.prefix)) {
      val = val.slice(this.prefix.length);
    }

    // Suffix entfernen für interne Verarbeitung
    if (this.suffix) {
      const suffixEscaped = this.escapeRegExp(this.suffix);
      const suffixRegex = new RegExp(`(${suffixEscaped})+$`);
      val = val.replace(suffixRegex, '');
    }

    // Alle Separatoren entfernen und unzulässige Zeichen filtern
    const sepEscaped = this.escapeRegExp(this.separator);
    val = val.replace(new RegExp(sepEscaped, 'g'), '').replace(/[^\w]/g, '');

    const cleanValue = val;
    let formatted = '';
    let pos = 0;

    // Formatierung der einzelnen Blöcke
    for (let i = 0; i < this.blocks.length; i++) {
      const len = this.blocks[i];
      const type = this.blockTypes[i] || 'numeric';
      let slice = cleanValue.slice(pos, pos + len);

      // letzten Block auf maximale Länge begrenzen
      if (i === this.blocks.length - 1) {
        slice = slice.slice(0, len);
      }

      // Block entsprechend Typ filtern und formatieren
      const block = this.processBlock(slice, type).slice(0, len);
      pos += len;

      formatted += block;

      // Separator zwischen Blöcken hinzufügen, außer nach letztem Block
      if (block.length === len && i < this.blocks.length - 1) {
        formatted += this.separator;
      }
    }

    // Suffix nur hinzufügen, wenn Eingabe komplett
    if (cleanValue.length >= this.totalLength) {
      formatted += this.suffix;
    }

    // Prefix hinzufügen
    if (this.prefix) {
      formatted = this.prefix + formatted;
    }

    // Wert zurücksetzen
    this.element.value = formatted;
  }

  processBlock(text, type) {
    switch (type) {
      case 'numeric':
        return text.replace(/\D/g, '');
      case 'alpha':
        return text.replace(/[^a-zA-Z]/g, '');
      case 'alphanumeric':
        return text.replace(/[^a-zA-Z0-9]/g, '');
      case 'uppercase':
        return text.replace(/[^a-zA-Z]/g, '').toUpperCase();
      case 'upperalphanumeric':
        return text.replace(/[^a-zA-Z0-9]/g, '').toUpperCase();
      case 'lowercase':
        return text.replace(/[^a-zA-Z]/g, '').toLowerCase();
      case 'loweralphanumeric':
        return text.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
      default:
        return text.replace(/\D/g, '');
    }
  }

  escapeRegExp(string) {
    // RegExp-sichere Escapes für spezielle Zeichen
    return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  }
}
function checkLocationExists(obj) {
  checkLocationExistsCall(obj.val(), function (exists, locationData) {
    if (exists) {
      //console.log(locationData.name)
      obj.val(locationData.name);
    } else {
      alert("Diesen Ort gibt es nicht im System.");
      obj.val("");
    }
  });
}
function checkLocationInRiesExists(obj) {
  checkLocationInRiesExistsCall(obj.val(), function (exists, locationData) {
    if (exists) {
      //console.log(locationData.name)
      obj.val(locationData.name);
    } else {
      alert("Diesen Ort gibt es nicht im Landkreis Donau-Ries.");
      obj.val("");
    }
  });
}
function checkLocationInRiesExistsCall(placeName, callback) {
  $.ajax({
    url: "https://nominatim.openstreetmap.org/search",
    data: {
      q: placeName,
      format: "json",
      addressdetails: 1,
      limit: 5
    },
    success: function (data) {
      if (data.length > 0) {
        // Filtere nach Orten mit gültigen Klassen/Typen
        const validTypes = ["city", "town", "village", "hamlet", "municipality"];

        // Finde erstes Ergebnis, das passt und im Landkreis Donau-Ries liegt
        const found = data.find(item => {
          const isPlace = (item.class === "place" && validTypes.includes(item.type)) ||
            (item.class === "boundary" && item.type === "administrative");

          if (!isPlace) return false;

          const address = item.address || {};
          const county = (address.county || "").toLowerCase();
          const state = (address.state || "").toLowerCase();

          // Prüfe ob Landkreis Donau-Ries (case-insensitive) im Landkreis-Feld vorkommt
          return county.includes("donau-ries") && state.includes("bayern");
        });

        if (found) {
          callback(true, found);
        } else {
          callback(false, null);
        }
      } else {
        callback(false, null);
      }
    },
    error: function (xhr, status, error) {
      console.error("Fehler bei der Anfrage:", error);
      callback(false, null);
    }
  });
}
function checkLocationExistsCall(placeName, callback) {
  $.ajax({
    url: "https://nominatim.openstreetmap.org/search",
    data: {
      q: placeName,
      format: "json",
      addressdetails: 1,
      limit: 1
    },
    success: function (data) {
      if (data.length > 0) {
        const result = data[0];
        //console.log("Debug:", result.class, result.type, result.display_name);

        // Primäre gültige Kombinationen für echte Orte
        const isRealPlace =
          (result.class === "place" && ["city", "town", "village", "hamlet", "municipality"].includes(result.type)) ||
          (result.class === "boundary" && result.type === "administrative");

        if (isRealPlace) {
          callback(true, result);
        } else {
          callback(false, null);
        }
      } else {
        callback(false, null);
      }
    },
    error: function (xhr, status, error) {
      console.error("Fehler bei der Anfrage:", error);
      callback(false, null);
    }
  });
}
function getPLZ2Ort(ort, plz) {
  const url = 'https://nominatim.openstreetmap.org/search';
  $.ajax({
    url: url,
    data: {
      postalcode: plz,
      country: 'Germany',
      format: 'json',
      addressdetails: 1,
      limit: 1
    },
    success: function (data) {
      if (data.length > 0 && data[0].address) {
        const address = data[0].address;
        ort.val(address.city || address.town || address.village || '');
      } else {
        ort.val('');
        //alert('PLZ nicht gefunden.');
      }
    },
    error: function () {
      //alert('Fehler bei der Ortssuche.');
    }
  });
}
function getAdress(ort, plz, strasse) {
  const url = 'https://nominatim.openstreetmap.org/search';

  $.ajax({
    url: url,
    data: {
      q: strasse + ', Deutschland',
      format: 'json',
      addressdetails: 1,
      limit: 1
    },
    success: function (data) {
      if (data.length > 0 && data[0].address) {
        const address = data[0].address;
        ort.val(address.city || address.town || address.village || '');
        plz.val(address.postcode || '');
      } else {
        ort.val('');
        plz.val('');
        //alert('Adresse nicht gefunden.');
      }
    },
    error: function () {
      //alert('Fehler beim Abrufen der Adresse.');
    }
  });
}

function dynamicHide() {
  function callDynamicFields() {
    $('[data-cn="XContainerInvisible"]').each(function () {
      $(this).addClass('short');
      const $rows = $(this).children('.dynamic-row');
      $rows.slice(1).each(function () {
        hideLabelsExceptFirst($(this));
      });
    });
  }
  function hideLabelsExceptFirst($container) {
    console.log($container);
    //$container.addClass('short');
    $container.find('label').hide();
  }
  callDynamicFields();

  $(document).on('change', 'input', function () {
    callDynamicFields();
  })

  $(document).on('click', 'div.add-button.dyn-icon', function () {
    callDynamicFields();
  });

  $(document).on('click', 'div.xm-del-button-icon.dyn-del-button', function () {
    callDynamicFields();
  });

}