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

        scope.$on('destroy_ancMapWidget', () => {
          $timeout(() => scope.$destroy(), 0);
          // dialog is closed automaticaly when scope is destoryed
        });

        scope.elementsFiliereVisibles = {
          efLayerAll: false,
          efLayerTraitement: false,
          efLayerPretraitement: false,
          efLayerAutres: false,
          efLayerAgrees: false,
          efCanalisations: false,
        };

        scope.saveSelectSource = '';
        scope.isSelecting = false;
        scope.isSelectingOne = false;

        scope.toggleLayerEF = function(x, forceValue) {
          if (x == 'efLayerAll') {
            scope.elementsFiliereVisibles.efLayerAll = !scope
              .elementsFiliereVisibles.efLayerAll;
            Object.keys(scope.elementsFiliereVisibles).forEach(function(layer) {
              if (layer != 'efLayerAll')
                scope.toggleLayerEF(
                  layer,
                  scope.elementsFiliereVisibles.efLayerAll
                );
            });
          } else {
            angular.isDefined(forceValue)
              ? (scope.elementsFiliereVisibles[x] = forceValue)
              : (scope.elementsFiliereVisibles[x] = !scope
                  .elementsFiliereVisibles[x]);

            scope.map.getLayers().forEach(function(lay) {
              if (lay.get('id') == x) {
                lay.setVisible(scope.elementsFiliereVisibles[x]);

                // force refresh
                var source = lay.getSource();
                var params = source.getParams();
                params.t = new Date().getMilliseconds();
                source.updateParams(lay);
              }
            });
            if (!forceValue) {
              // Update value for all layers check
              scope.elementsFiliereVisibles.efLayerAll =
                scope.elementsFiliereVisibles.efLayerTraitement &&
                scope.elementsFiliereVisibles.efLayerPretraitement &&
                scope.elementsFiliereVisibles.efLayerAutres &&
                scope.elementsFiliereVisibles.efLayerAgrees &&
                scope.elementsFiliereVisibles.efCanalisations;
            }
          }
        };
        scope.showAncPanel = () => { 
          scope.panelsManager.removePanel('ancMapPanel');
          AncAppFactory.getAppCfg(
            false,
            true,
            scope.ancapp.name
          ).then(()=> {
            scope.showAdminButton = AncAppFactory.appCfg.isAdmin;

            dossierFti = angular.copy(
              FeatureTypeFactory.getFeatureByNameAndDatastore(
                AncAppFactory.appCfg.main.datastore,
                'kis_anc_dossier'
              )
            );

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

        var map, dossierFti;
        scope.$on('openTools_ancmapwidget', () => {
          map = scope.map;
          if (scope.applicationFound) scope.showAncPanel();
        });

        scope.initAncPanel = function() {
          AncAppFactory.getAppCfg(false, true, scope.ancapp.name).then(
            function() {
              // acces au file manager autorisé
              var filemanager = angular.copy(
                AncAppFactory.appCfg.main.properties.filemanager
              );
              var canAccessFM = $rootScope.xgos.user.roles.filter(function(x) {
                return x.name.indexOf('ANC_rapports_') == 0;
              }).length;

              scope.allowGoToRapports =
                angular.isDefined(filemanager) &&
                filemanager.active &&
                ($rootScope.xgos.isroot || canAccessFM);

              scope.showAdminButton = AncAppFactory.appCfg.isAdmin;
              scope.showFilieresButtons =
                AncAppFactory.appCfg.main.properties.filieresVectorielles.active;

              dossierFti = angular.copy(
                FeatureTypeFactory.getFeatureByNameAndDatastore(
                  AncAppFactory.appCfg.main.datastore,
                  'kis_anc_dossier'
                )
              );

              if (
                AncAppFactory.appCfg.main.properties.filieresVectorielles.active
              ) {
                var portalId = PortalsFactory.getPortalId();
                var efWMS = new ol.layer.Tile({
                  id: 'efLayerAll',
                  source: new ol.source.TileWMS({
                    url:
                      '/services/' +
                      portalId +
                      '/geoserver/wms?token=' +
                      localStorage.auth_token,
                    params: {
                      LAYERS:
                        portalId +
                        ':lg_anc_ef_pretraitement,' +
                        portalId +
                        ':lg_anc_ef_traitement,' +
                        portalId +
                        ':lg_anc_ef_autre,' +
                        portalId +
                        ':lg_anc_ef_agree',
                      TILED: true,
                      CQL_FILTER:
                        'filiere_active=true;filiere_active=true;filiere_active=true;filiere_active=true;',
                    },
                    serverType: 'geoserver',
                    crossOrigin: 'anonymous',
                  }),
                });
                scope.map.addLayer(efWMS);

                var efWMSPTraitement = new ol.layer.Tile({
                  id: 'efLayerTraitement',
                  visible: false,
                  source: new ol.source.TileWMS({
                    url:
                      '/services/' +
                      PortalsFactory.getPortalId() +
                      '/geoserver/wms?token=' +
                      localStorage.auth_token,
                    params: {
                      LAYERS:
                        PortalsFactory.getPortalId() +
                        ':lg_anc_ef_traitement',
                      TILED: true,
                      CQL_FILTER: 'filiere_active=true',
                    },
                    serverType: 'geoserver',
                    crossOrigin: 'anonymous',
                  }),
                });

                var efWMSPretraitement = new ol.layer.Tile({
                  id: 'efLayerPretraitement',
                  visible: false,
                  source: new ol.source.TileWMS({
                    url:
                      '/services/' +
                      PortalsFactory.getPortalId() +
                      '/geoserver/wms?token=' +
                      localStorage.auth_token,
                    params: {
                      LAYERS:
                        PortalsFactory.getPortalId() +
                        ':lg_anc_ef_pretraitement',
                      TILED: true,
                      CQL_FILTER: 'filiere_active=true',
                    },
                    serverType: 'geoserver',
                    crossOrigin: 'anonymous',
                  }),
                });
                var efWMSAgrees = new ol.layer.Tile({
                  id: 'efLayerAgrees',
                  visible: false,
                  source: new ol.source.TileWMS({
                    url:
                      '/services/' +
                      PortalsFactory.getPortalId() +
                      '/geoserver/wms?token=' +
                      localStorage.auth_token,
                    params: {
                      LAYERS:
                        PortalsFactory.getPortalId() + ':lg_anc_ef_agree',
                      TILED: true,
                      CQL_FILTER: 'filiere_active=true',
                    },
                    serverType: 'geoserver',
                    crossOrigin: 'anonymous',
                  }),
                });
                var efWMSAutres = new ol.layer.Tile({
                  id: 'efLayerAutres',
                  visible: false,
                  source: new ol.source.TileWMS({
                    url:
                      '/services/' +
                      PortalsFactory.getPortalId() +
                      '/geoserver/wms?token=' +
                      localStorage.auth_token,
                    params: {
                      LAYERS:
                        PortalsFactory.getPortalId() + ':lg_anc_ef_autre',
                      TILED: true,
                      CQL_FILTER: 'filiere_active=true',
                    },
                    serverType: 'geoserver',
                    crossOrigin: 'anonymous',
                  }),
                });

                var efCanalisations = new ol.layer.Tile({
                  id: 'efCanalisations',
                  visible: false,
                  source: new ol.source.TileWMS({
                    url:
                      '/services/' +
                      PortalsFactory.getPortalId() +
                      '/geoserver/wms?token=' +
                      localStorage.auth_token,
                    params: {
                      LAYERS: portalId + ':kis_anc_efx_canalisations',
                      TILED: true,
                      CQL_FILTER: 'filiere_active=true',
                      STYLES: portalId + ':kis_anc_efx_canalisations',
                    },
                    serverType: 'geoserver',
                    crossOrigin: 'anonymous',
                  }),
                });

                scope.map.addLayer(efWMS);
                scope.map.addLayer(efWMSPTraitement);
                scope.map.addLayer(efWMSPretraitement);
                scope.map.addLayer(efWMSAgrees);
                scope.map.addLayer(efWMSAutres);
                scope.map.addLayer(efCanalisations);

                scope.toggleLayerEF('efLayerAll'); // Select all on load
              }
            }
          );
        };

        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.addNewAncDossier = () => {
          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';
                var 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 () {
          const data = {
            feature: angular.copy(scope.newDossierGeometry),
            adresse: scope.newDossierAdresse,
            newFromMap: true,
          };
          $rootScope.$broadcast('preset_anc_dossier', data);
          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) {
            var wktObj = new ol.format.WKT();
            var wktStr = wktObj.writeGeometry(evt.feature.getGeometry());
            
            if (dossierFti == undefined) {
              AncAppFactory.getAppCfg(false, true, scope.ancapp.name).then(
                function() {
                  dossierFti = angular.copy(
                    FeatureTypeFactory.getFeatureByNameAndDatastore(
                      AncAppFactory.appCfg.main.datastore,
                      'kis_anc_dossier'
                    )
                  );
                  scope.resetSelection();

                  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();
                      SelectManager.clear();
                      require('toastr').error(
                        $filter('translate')('layermanager.no_selectable_layer')
                      );
                    } else {
                      scope.dossierSelectionnesMap = res.data.features.map(
                        function(x) {
                          return x.properties.ref_dossier;
                        }
                      );
                      gclayers
                        .getDrawLayer()
                        .getSource()
                        .clear();
                    }
                  });
                }
              );
            } else {
              scope.resetSelection();

              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();
                  SelectManager.clear();
                  require('toastr').error(
                    $filter('translate')('layermanager.no_selectable_layer')
                  );
                } else {
                  scope.dossierSelectionnesMap = res.data.features.map(function(
                    x
                  ) {
                    return x.properties.ref_dossier;
                  });
                  gclayers
                    .getDrawLayer()
                    .getSource()
                    .clear();
                }
              });
            }

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

        /**
         * setSelectInteraction
         * Set the select interaction
         */
        var setSelectInteractionPoint = function() {
          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 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();
                  SelectManager.clear();
                  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;
                  scope.openDossier(scope.selectedDossier);
                  map.removeInteraction(scope.selectDossierInteractionPoint);
                }
                scope.resetSelection();
              });

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

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

        scope.openDossier = function(dossier) {
          $rootScope.$broadcast('anc_open_dossier', dossier);
        };

        /**
         * When selecting anc dossiers
         */
        scope.selectAncDossiers = function() {
          if (!scope.isSelecting) {
            scope.resetSelection();
            scope.map.addInteraction(scope.selectDossierInteractionPolygon);
            scope.isSelecting = true;
          } else {
            scope.resetSelection();
            scope.isSelecting = false;
          }

          scope.saveSelectSource = gclayers.getselectSource();
        };

        /**
         * When selecting anc dossier by clic
         */
        scope.selectAncDossier = function() {
          if (!scope.isSelectingOne) {
            scope.resetSelection();
            scope.map.addInteraction(scope.selectDossierInteractionPoint);
            scope.isSelectingOne = true;
          } else {
            scope.resetSelection();
            scope.isSelectingOne = false;
          }
        };

        /**
         * 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();
          }

          removeInteractionsFromMap();

          gclayers.clearhighLightFeatures();
          SelectManager.clear();

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

          scope.dossierSelectionnesMap = false;
          scope.dossierSelectionneMap = false;
          scope.isSelecting = false;
          scope.isSelectingOne = false;
          scope.isAddingDossier = false;
        };

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


          scope.initAncPanel();
        };

        /**
         * goToAncPanel
         */
        scope.goToAncPanel = function(page) {
          var hash = '';
          if (page == 'rapports') {
            page = 'documents';
            hash = '#rapports';
          }
          $window.open(
            '#/anc/' +
              page +
              '/?portal=' +
              PortalsFactory.getPortalId() +
              '&app=' +
              scope.ancapp.name +
              hash
          );
        };
        scope.$on('ancmapwidget_tool_click', () => {
          //when tool is closed
          gclayers
            .getDrawLayer()
            .getSource()
            .clear();
        });
        scope.$on("openTools_ancmapwidget", () => {
          $rootScope.xgos.sub_sector = 'anc';
        })
      },
    };
  };

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