'use strict'
define(function() {
  const geolocalisationbutton = ($filter, gaJsUtils, GeolocalisationService, kisGeocodageFactory,
      mapJsUtils, $rootScope, ConfigFactory) => {
    return {
      templateUrl:'js/XG/widgets/mapapp/geolocalisation/views/geolocalisationbutton.html',
      restrict: 'AE',
      link: (scope) => {
        scope.inputAddress = {value: ''};

        /**
         * A l'appui de la touche "Entrée" quand le texte saisi est de 3 caractères minimum,
         * récupère la liste des résultats correspondant à la saisie parmi les géocodeurs actifs
         * définis dans les paramètres du portail.
         * Les géocodeurs actifs respectent la priorité suivante: KIS>OSM>GOOGLE
         * Affiche le 1er résultat dans un toastr-success, affiche un toastr-warn quand aucun résultat
         * Exécute l'affichage du marqueur dans la carte à la position de l'adresse
         * @param {KeyboardEvent} event appui d'une touche clavier
         */
        scope.showAddress = (event) => {

          if (event.key === 'Backspace' || event.key === 'Delete') {
            // Vérifie que du texte de l'input soit en surbrillance
            const isSelectingInputText = gaJsUtils.notNullAndDefined(window.getSelection().getRangeAt(0),
                'commonAncestorContainer.parentElement.parentElement')
                && window.getSelection().getRangeAt(
                    0).commonAncestorContainer.parentElement.parentElement.classList.contains(
                    'geolocalisation-button');

            // Vérifie que la longueur du texte en surbrillance corresponde à la longueur du texte de l'input
            const isSelectingAllText =  window.getSelection().toString().length === scope.inputAddress.value.length;

            // Vérifie que tout le texte de l'input soit en surbrillance
            const allTextDeleted = isSelectingInputText && isSelectingAllText;

            // Vérifie que le texte soit effacé par la touche "Backspace"
            const backspacePushed = event.key === 'Backspace' && scope.inputAddress.value.length === 1;

            // Vérifie que le texte soit effacé par la touche "Suppression" avec le curseur en début d'input
            const supprPushedOnStart = event.key === 'Delete' && event.currentTarget.selectionStart === 0
                && scope.inputAddress.value.length === 1;

            if (scope.markerLayer && ((backspacePushed || supprPushedOnStart) || (allTextDeleted))) {
              clear();
            }
          }

          if (event.key === 'Enter' && scope.inputAddress.value.length > 2) {
            GeolocalisationService.getAddresses(scope.inputAddress).then(
                res => {
                  if (res.length === 0) {
                    require('toastr').warning($filter('translate')('portals.geocodage.noResult'));
                  } else {
                    const address = res[0];

                    // Affichage de la puce géographique
                    showMarker(address);

                    // construction du toastr
                    // KIS-3419: "équivalent à ce qui est présenté dans le widget"
                    const latLabel = $filter('translate')('portals.geocodage.lat');
                    const lonLabel = $filter('translate')('portals.geocodage.lon');
                    const success =
                        `
                          <div class="title">
                            <span>${address.address.state}</span>
                            <span>${address.origin}</span>
                          </div>
                          <div class="content">
                            <div>
                              <span>${address.display_name}</span>
                            </div>
                            <div>
                              <div>
                                <span class="desc">${latLabel}</span><span>${address.lat}</span>
                              </div>
                              <div>
                                <span class="desc">${lonLabel}</span><span>${address.lon}</span>
                              </div>
                            </div>
                          </div>
                        `
                    // personnalisation css du toastr
                    require('toastr').success(success, null, {iconClass: 'geocoder'});
                  }
                }
            );
          }
        };

        /**
         * Au clic sur le bouton "Vider" (croix),
         * suppression de la saisie et suppression du marqueur
         */
        scope.clearAddress = () => {
          scope.inputAddress.value = '';
          clear();
        };

        /**
         * Au clic sur le bouton de l'outil,
         * marque l'état de la popover (ouverte/fermée).
         * Permet de supprimer le marqueur de la carte lorsque l'outil est refermé
         */
        scope.togglePopover = () => {
          scope.isPopoverOpen = !scope.isPopoverOpen;
          if (scope.isPopoverOpen) {
            if (scope.allowTool) {
              GeolocalisationService.getConfig();
            } else {
              require('toastr').warning($filter('translate')('geolocalisation.noWidget'));
            }
          } else {
            clear();
          }
        };

        /**
         * Récupère les paramètres des géocodeurs du portail et récupère les résultats de localisation
         * correspondant à la saisie de l'utilisateur.
         * Tous les géocodeurs actifs sont interrogés
         * @return {Promise} contient un tableau des résultats. Retour du tableau uniquement après
         * que tous les géocodeurs actifs aient répondu
         */

        /**
         * Récupère la couche de la puce de géolocalisation.
         * Affiche la puce de géolocalisation à la position de l'adresse fournie en paramètre
         * Projection de l'adresse fournie dans la projection de la carte
         * @param {object} address premier résultat issu de la méthode #getAddress interrogeant les géocodeurs
         */
        const showMarker = (address) => {
          scope.markerLayer = kisGeocodageFactory.getMarkerLayer();
          scope.markerLayer.set('name','geocodage-layer');
          scope.markerLayer.getSource().clear();
          const srid = scope.map.getView().getProjection().getCode();
          const lat = Number(address.lat);
          const lon = Number(address.lon);
          const projectedCoords = ol.proj.transform([lon, lat], 'EPSG:4326', srid);
          scope.map.getView().setCenter(projectedCoords);
          const addressFeature = new ol.Feature({
            name: address.display_name
          });
          addressFeature.setGeometry(new ol.geom.Point(projectedCoords));
          scope.markerLayer.getSource().addFeature(addressFeature);
          scope.markerLayer.setZIndex(gaJsUtils.getZIndexMax(scope.map) + 1);
          scope.map.addLayer(scope.markerLayer);
        };

        /**
         * Vide la couche du marqueur
         * Enlève la couche de la carte
         */
        const clear = () => {
          if (scope.markerLayer) {
            scope.markerLayer.getSource().clear();
            if (mapJsUtils.mapHasLayerByName(scope.map,'geocodage-layer')) {
              scope.map.removeLayer(scope.markerLayer);
            }
          }
        };

        /**
         * Réception de la vérification de la présence du widget "Localisation à l'adresse"
         * Evènement envoyé depuis gcmaincontroller à l'enregistrement de la configuration des widgets
         */
        scope.$on('hasGeolocalisationWidget', (event, hasGeolocalisationWidget) => {
          scope.allowTool = hasGeolocalisationWidget;
        });

        /**
         * INITIALISATION
         * Vérifie la présence du widget "Localisation à l'adresse"
         */
        ConfigFactory.get('main', 'tools').then(
            res => {
              if (res.data.code !== 403) {
                scope.allowTool = GeolocalisationService.hasGeolocalisationWidget(res.data);
              } else {
                console.error($filter('translate')('geolocalisation.unableFindWidget'));
                scope.allowTool = false;
              }
            },
            err => {
              scope.allowTool = false;
              console.error($filter('translate')('geolocalisation.unableFindWidget'));
              console.error(err.data);
            }
        );

      }
    };
  };
  geolocalisationbutton.$inject = ['$filter', 'gaJsUtils', 'GeolocalisationService',
    'kisGeocodageFactory', 'mapJsUtils', '$rootScope', 'ConfigFactory'];
  return geolocalisationbutton;
});
