'use strict';
define(function() {
  var bacMapWidget = function(
    BacAppFactory,
    ApplicationFactory,
    FeatureTypeFactory,
    gclayers,
    ogcFactory,
    SelectManager,
    $timeout,
    $rootScope,
    $http,
    $filter,
    $window,
    GeometryFactory,
    gaJsUtils,
    ngdialog,
    extendedNgDialog,
    PortalsFactory
  ) {
    return {
      templateUrl: 'js/XG/widgets/bacapp/main/views/map/bac_map_widget.html',
      restrict: 'EA',
      link: function(scope) {
        scope.applicationFound = false;
        ApplicationFactory.get().then(() => {
          const applications = ApplicationFactory.resources.applications;
          for (let i in applications) {
            if (applications.hasOwnProperty(i) && applications[i].type === 'BacApp') {
              scope.bacapp = {
                name: applications[i].name,
              };
              scope.applicationFound = true;
              break;
            }
          }
        });

        $rootScope.xgos.sub_sector = 'bac';

        scope.$on('destroy_bacMapWidget', () => {
          //scope.panelsManager.removePanel('bacMapPanel');
          $timeout(() => scope.$destroy(), 0);
        });

        scope.saveSelectSource = '';

        let dossierFti;
        scope.isSelecting = false;
        scope.isSelectingOne = false;

        scope.$on('openTools_bacmapwidget', function() {
          if (scope.applicationFound) scope.initBacPanel();
        });

        //scope.panelVisible = false;
        scope.initBacPanel = () => {
          scope.panelsManager.removePanel('bacMapPanel');
          BacAppFactory.getAppCfg(false, true, scope.bacapp.name).then(
            () => {
              scope.showAdminButton = BacAppFactory.appCfg.isAdmin;

              dossierFti = angular.copy(
                FeatureTypeFactory.getFeatureByNameAndDatastore(
                  BacAppFactory.appCfg.main.datastore,
                  'kis_bac_dossier'
                )
              );

              // initialise la directive listeDossiersBac nécessaire
              scope.panelsManager.addPanel({
                id: 'bacMapPanel',
                stickToRight: true,
                templateUrl:
                  'js/XG/widgets/bacapp/main/views/map/bac_map_panel.html',
                scope: scope,
                stickToBorder: true,
                resizable: true,
                visible: false
              });
            }
          );
        };

        var drawStyle = new ol.style.Style({
          image: new ol.style.Circle({
            radius: 7,
            fill: new ol.style.Fill({
              color: '#3498db',
            }),
          }),
        });

        var features = new ol.Collection();

        var collection = new ol.Collection();
        var featureOverlay = new ol.layer.Vector({
          map: scope.map,
          source: new ol.source.Vector({
            features: collection,
            useSpatialIndex: false, // optional, might improve performance
          }),
          style: drawStyle,
          updateWhileAnimating: true, // optional, for instant visual feedback
          updateWhileInteracting: true, // optional, for instant visual feedback
        });

        let drawNewDossier;

        scope.newDossierGeometry = false;
        scope.newDossierAdresse = false;
        scope.isAddingDossier = false;
        scope.addNewBacDossier = () => {
          scope.map.removeInteraction(scope.selectDossierInteraction);
          scope.map.removeInteraction(drawNewDossier);

          if (!scope.isAddingDossier) {
            scope.resetSelection();
            drawNewDossier = new ol.interaction.Draw({
              features: features,
              type: 'Point',
              style: drawStyle,
            });
            scope.map.addInteraction(drawNewDossier);
            scope.isAddingDossier = true;

            drawNewDossier.on('drawend', (e) => {
              $timeout(() => {
                const currentCoords = e.feature.getGeometry().getCoordinates();
                const currentProj = scope.map
                  .getView()
                  .getProjection()
                  .getCode();

                const latlon = ol.proj.transform(
                  currentCoords,
                  currentProj,
                  'EPSG:4326'
                );
                const service = 'ban';
                const url = gaJsUtils.getUrlReverseGeocoder(latlon, service);

                const format = new ol.format.GeoJSON();

                // la localisation des dossiers est sauvegardée dans la projection 3857
                const toSaveCoords = currentProj === 'EPSG:3857' ? currentCoords
                    : ol.proj.transform(currentCoords, currentProj, 'EPSG:3857');

                const feature = format.writeFeatureObject(
                  new ol.Feature({
                    geometry: new ol.geom.Point(toSaveCoords),
                  })
                );
                scope.map.removeInteraction(drawNewDossier);
                scope.resetSelection();

                $http.get(url).then(
                  (res) => {
                    if (res.data) {
                      const newRes = gaJsUtils.transformGeocoderRes(
                        res,
                        scope.service
                      );
                      scope.newDossierGeometry = feature;
                      scope.newDossierAdresse =
                        newRes.data.features['0'].properties;
                      scope.doAddDossier();
                    }
                    scope.newDossierGeometry = feature;
                  },
                  () => {
                    scope.newDossierGeometry = feature;
                  }
                );
              });
            });
          } else {
            scope.newDossierGeometry = false;
            scope.map.removeInteraction(drawNewDossier);
            scope.resetSelection();
            scope.isAddingDossier = false;
          }
        };

        /**
         * doAddDossier
         */
        scope.doAddDossier = function() {
          $rootScope.$broadcast('preset_bac_dossier', {
            feature: angular.copy(scope.newDossierGeometry),
            adresse: scope.newDossierAdresse,
            newFromMap: true,
          });
          scope.newDossierGeometry = false;
          scope.isAddingDossier = false;
        };

        /**
         * setSelectInteraction
         * Set the select interaction
         */
        var setSelectInteraction = function() {
          scope.selectDossierInteractionPolygon = new ol.interaction.Draw({
            source: gclayers.getDrawLayer().getSource(),
            type: 'Polygon',
          });

          scope.selectDossierInteractionPolygon.on('drawend', function(evt) {
            
            if (!dossierFti) {
              BacAppFactory.getAppCfg(false, true, scope.bacapp.name).then(() => {
                dossierFti = angular.copy(
                  FeatureTypeFactory.getFeatureByNameAndDatastore(
                    BacAppFactory.appCfg.main.datastore,
                    'kis_bac_dossier'
                  )
                );
                setSelectedDossiers(evt);
              }).catch(() => {
                require('toastr').error(
                  $filter('translate')('message.general_error')
                );
              });
            } else {
              setSelectedDossiers(evt);
            }

            scope.isSelecting = false;
          });
        };
        setSelectInteraction();

        /**
         * setSelectInteraction
         * Set the select interaction
         */
        var setSelectInteractionPoint = function() {
          var resolution;

          scope.selectDossierInteractionPoint = new ol.interaction.Draw({
            source: gclayers.getDrawLayer().getSource(),
            type: 'Point',
          });

          scope.selectDossierInteractionPoint.on('drawend', function(evt) {
            var geoJsonObj = new ol.format.GeoJSON();
            var geoJsonStr = geoJsonObj.writeGeometry(
              evt.feature.getGeometry()
            );

            var bufferedGeoJson = GeometryFactory.buffer(geoJsonStr, 'FLAT', 1);

            bufferedGeoJson.then(function(res) {
              evt.feature.setGeometry(geoJsonObj.readGeometry(res.data));

              //Conversion de l'objet en WKT
              var wktObj = new ol.format.WKT();

              var spatialClause = 'INTERSECTS(geom, ' + wktObj + ')';

              var wktStr = wktObj.writeGeometry(
                geoJsonObj.readGeometry(res.data)
              );

              var promise = ogcFactory.getfeaturespost(
                'INTERSECTS(geom, ' + wktStr + ')',
                dossierFti.uid,
                scope.map
                  .getView()
                  .getProjection()
                  .getCode()
              );
              promise.then(function(res) {
                SelectManager.addFeaturesFromGeojson(res.data);
                if (res.data.totalFeatures == 0) {
                  gclayers.clearhighLightFeatures();
                  scope.resetSelection();
                  require('toastr').error(
                    $filter('translate')('layermanager.no_selectable_layer')
                  );
                } else {
                  scope.selectedDossier = res.data.features.map(function(x) {
                    return x;
                  });

                  scope.dossierSelectionneMap =
                    scope.selectedDossier[0].properties.ref_dossier;
                  scope.isSelectingOne = false;
                  openDossier(scope.selectedDossier);
                  scope.resetSelection();
                }
              });

              gclayers
                .getDrawLayer()
                .getSource()
                .clear();
            });

            scope.isSelectingOne = false;
            scope.saveSelectSource = gclayers.getselectSource();
          });
        };
        setSelectInteractionPoint();

        var openDossier = function(dossier) {
          $rootScope.$broadcast('bac_open_dossier', dossier);
        };

        /**
         * When selecting bac dossiers
         */
        scope.selectBacDossiers = function() {


          if (!scope.isSelecting) {
            scope.resetSelection();
            scope.map.addInteraction(scope.selectDossierInteractionPolygon);
            scope.isSelecting = true;
          } else {
            scope.resetSelection();
            scope.isSelecting = false;
          }
        };

        /**
         * When selecting bac dossier by clic
         */
        scope.selectBacDossier = function() {


          if (!scope.isSelectingOne) {
            scope.resetSelection();
            scope.map.addInteraction(scope.selectDossierInteractionPoint);
            scope.isSelectingOne = true;
          } else {
            scope.resetSelection();
            scope.isSelectingOne = false;
          }
          scope.saveSelectSource = gclayers.getselectSource();
        };

        /**
         * resetSelection
         */
        scope.resetSelection = function() {
          let removeInteractionsFromMap = () => {
            // Remove all interactions in order to stay in a stable state
            // Interactions: selection par point, selection polygonnale, ajout dossier

            if (scope.selectDossierInteractionPolygon) {
              scope.map.removeInteraction(scope.selectDossierInteractionPolygon);
            }
            
            if (angular.isDefined(scope.selectDossierInteractionPoint)) {
              scope.map.removeInteraction(scope.selectDossierInteractionPoint);
            }

            if (angular.isDefined(drawNewDossier)) {
              scope.map.removeInteraction(drawNewDossier);
            }
          }

          if (scope.saveSelectSource != '' && scope.saveSelectSource !== undefined){
            scope.saveSelectSource.clear();
            gclayers.clearhighLightFeatures();
          }

          removeInteractionsFromMap();

          gclayers
            .getDrawLayer()
            .getSource()
            .clear();

          gclayers.clearhighLightFeatures();
          SelectManager.clear();
          scope.dossierSelectionnesMap = false;
          scope.dossierSelectionneMap = false;
          scope.isSelecting = false;
          scope.isSelectingOne = false;
          scope.isAddingDossier = false;
        };

/*         scope.closeBacPanel = function() {
          scope.panelsManager.hidePanel('bacMapPanel');
          scope.panelVisible = false;
        }; */

        
        scope.openBacDialog = function() {
          
          extendedNgDialog.open({
            template: 'js/XG/widgets/bacapp/main/views/map/bac_map_panel.html',
            className:
              'ngdialog-theme-default ' + 'height500' + ' nopadding miniclose' + ' width1100',
            closeByDocument: true,
            scope: scope,
            minimizeMaximize: true,
            scrollable: true,
            resizable: true,
            title: $filter('translate')('gcbacwidget.widgetname'),
            draggable: true,
            preCloseCallback: function () {
              gclayers.getDrawLayer().getSource().clear();
              gclayers.clearhighLightFeatures();
              SelectManager.clear();
            },
          });
          scope.initBacPanel();
        }

        scope.toggleBacPanel = function() {
          if (scope.panelVisible) {
            scope.closeBacPanel();
          } else {
            scope.panelsManager.showPanel('bacMapPanel');
            scope.panelVisible = true;
          }
        };

        /**
         * goToBacPanel
         */
        scope.goToBacPanel = function(page) {
          var hash = '';
          if (page == 'rapports') {
            page = 'documents';
            hash = '#rapports';
          }
          $window.open(
            '#/bac/' +
              page +
              '/?portal=' +
              PortalsFactory.getPortalId() +
              '&app=' +
              scope.bacapp.name +
              hash
          );
        };
        function setSelectedDossiers(evt) {
          const wktObj = new ol.format.WKT();
          const wktStr = wktObj.writeGeometry(evt.feature.getGeometry());
          scope.resetSelection();
          const mapProjectionCode = scope.map
            .getView()
            .getProjection()
            .getCode();
          ogcFactory.getfeaturespost(
            'INTERSECTS(geom, ' + wktStr + ')',
            dossierFti.uid,
            mapProjectionCode
          ).then(res => {
            SelectManager.addFeaturesFromGeojson(res.data);
            if (res.data.totalFeatures == 0) {
              gclayers.clearhighLightFeatures();
              SelectManager.clear();
              require('toastr').error(
                $filter('translate')('layermanager.no_selectable_layer')
              );
            } else {
              scope.dossierSelectionnesMap = res.data.features
                .map(x => x.properties.ref_dossier);
              
              gclayers
                .getDrawLayer()
                .getSource()
                .clear();
            }
          }).catch(() => {
            gclayers.clearhighLightFeatures();
            SelectManager.clear();

            require('toastr').error(
              $filter('translate')('message.general_error')
            );
          });
        }
        scope.$on('bacmapwidget_tool_click', () => {
          //when tool is closed
          gclayers
            .getDrawLayer()
            .getSource()
            .clear();
        });
      },
    };
  };

  bacMapWidget.$inject = [
    'BacAppFactory',
    'ApplicationFactory',
    'FeatureTypeFactory',
    'gclayers',
    'ogcFactory',
    'SelectManager',
    '$timeout',
    '$rootScope',
    '$http',
    '$filter',
    '$window',
    'GeometryFactory',
    'gaJsUtils',
    'ngDialog',
    'extendedNgDialog',
    'PortalsFactory'
  ];
  return bacMapWidget;
});
