'use strict';
define(function() {
  var GoogleMapsFactory = function(
    $window,
    $q,
    $rootScope,
    $http,
    gaJsUtils,
    $filter
  ) {
    var GoogleMapsFactory = {};
    /**
     * Class : GoogleMapsFactory
     * Factory WebServices
     */
    /**
     * LazyLoad GoogleStreetView script
     * @returns {*}
     */
    function lazyLoad() {
      var body = angular
        .element(document)
        .find('body')
        .eq(0);
      body.addClass('waitCursor');
      var deferred = $q.defer(),
        resolve = function() {
          body.removeClass('waitCursor');
          deferred.resolve();
        };
      if ($window.google && $window.google.maps) {
        console.log('Gmap Already Loaded');
        resolve();
      } else {
        var googleKey = false;
        var _gk = gaJsUtils.checkNestedProperty(
          'portal.parameters.apikey.google',
          $rootScope.xgos
        );
        if (_gk && _gk.trim() != '') {
          googleKey = $rootScope.xgos.portal.parameters.apikey.google;
        }
        var s = document.createElement('script'); // use global document since Angular's $document is weak
        var langage = localStorage.getItem('current_language');
        s.src =
          'https://maps.googleapis.com/maps/api/js?sensor=false&callback=initialize&language=' +
          langage;
        if (googleKey) s.src += '&key=' + googleKey;
        document.body.appendChild(s);
        $window.initialize = function() {
          resolve();
          require('toastr').clear();
          //require('toastr').success($filter('translate')('common.gmap_loaded'));
        };
      }
      return deferred.promise;
    }
    /**
     * Transform evt.coordinate into EPSG:4326
     * and return a google.maps.LatLng object
     * @param coordinate
     * @param projection
     * @returns {google.maps.LatLng}
     */
    function coordinatesToLatLng(coordinate, projection, notGoogle) {
      var transformCoordinates = ol.proj.transform(
          [coordinate[0], coordinate[1]],
          projection,
          'EPSG:4326'
        ),
        lat = Math.round(transformCoordinates[1] * 10000000) / 10000000,
        lng = Math.round(transformCoordinates[0] * 10000000) / 10000000;
      if (notGoogle) {
        return [lng, lat];
      } else {
        return new google.maps.LatLng(lat, lng);
      }
    }
    /**
     * Transform gmap LatLng to coordinates in the map current projection
     * @param position
     * @param projection
     * @returns {ol.Coordinate}
     */
    function latLngTocoordinates(position, projection) {
      return ol.proj.transform(
        [position.lng, position.lat],
        'EPSG:4326',
        projection
      );
    }
    /**
     * set the dragable layers
     * @param dragableLayers
     * @returns {Drag}
     */
    function setDragableLayers(dragableLayers) {
      var Drag = function() {
        ol.interaction.Pointer.call(this, {
          handleDownEvent: Drag.prototype.handleDownEvent,
          handleDragEvent: Drag.prototype.handleDragEvent,
          handleMoveEvent: Drag.prototype.handleMoveEvent,
          handleUpEvent: Drag.prototype.handleUpEvent,
        });
        this.dragableLayers = dragableLayers;
        this.coordinate_ = null;
        this.cursor_ = 'pointer';
        this.feature_ = null;
        this.previousCursor_ = undefined;
      };
      ol.inherits(Drag, ol.interaction.Pointer);
      Drag.prototype.handleDownEvent = function(evt) {
        var featureLayer = evt.map.forEachFeatureAtPixel(evt.pixel, function(
          feature,
          layer
        ) {
          return [feature, layer];
        });
        /* Only allowed Layers */
        if (featureLayer && featureLayer[0]) {
          if (this.dragableLayers.indexOf(featureLayer[1]) != -1) {
            this.coordinate_ = evt.coordinate;
            this.feature_ = featureLayer[0];
          }
          return !!featureLayer[0];
        } else {
          return false;
        }
      };
      Drag.prototype.handleDragEvent = function(evt) {
        /* Only allowed Layers */
        if (this.feature_ != null) {
          var deltaX = evt.coordinate[0] - this.coordinate_[0];
          var deltaY = evt.coordinate[1] - this.coordinate_[1];
          this.feature_.getGeometry().translate(deltaX, deltaY);
          this.feature_.moving = true;
          this.coordinate_[0] = evt.coordinate[0];
          this.coordinate_[1] = evt.coordinate[1];
        }
      };
      Drag.prototype.handleMoveEvent = function(evt) {
        if (this.cursor_) {
          /* Only allowed Layers */
          var feature = evt.map.forEachFeatureAtPixel(evt.pixel, function(
            feature,
            layer
          ) {
            if (this.dragableLayers.indexOf(layer) != -1) {
              return feature;
            }
          });
          var element = evt.map.getTargetElement();
          if (feature) {
            if (element.style.cursor != this.cursor_) {
              this.previousCursor_ = element.style.cursor;
              element.style.cursor = this.cursor_;
            }
          } else if (this.previousCursor_ !== undefined) {
            element.style.cursor = this.previousCursor_;
            this.previousCursor_ = undefined;
          }
        }
      };
      Drag.prototype.handleUpEvent = function(evt) {
        if (this.feature_) {
          this.feature_.moving = false;
        }
        this.coordinate_ = null;
        this.feature_ = null;
        return false;
      };
      return new Drag();
    }
    /* urls des services */
    function getInformationsFromCoordinates(latlng, apikey) {
      return $http.get(
        'https://maps.googleapis.com/maps/api/geocode/json?latlng=' +
          latlng.lat() +
          ',' +
          latlng.lng() +
          '&key=' +
          apikey
      );
    }
    function getInformationsFromAddress(apikey, params) {
      return $http.get(
        'https://maps.googleapis.com/maps/api/geocode/json?key=' + apikey,
        {
          params: params,
        }
      );
    }
    function getElevationFromOpenRoute(coordinatesLatLng) {
      return $http({
        url: 'https://api.openrouteservice.org/elevation/line',
        method: 'POST',
        data: {
          format_in: 'polyline',
          format_out: 'geojson',
          geometry: coordinatesLatLng,
        },
        headers: {
          Authorization: $rootScope.xgos.portal.parameters.apikey.openroute,
        },
      });
    }
    function typeOfApiUsed() {
      const ign = $rootScope.xgos.portal.parameters.apikey.ign;
      if (ign && ign.trim() != '') {
        return 'ign';
      } else {
        const openroute = $rootScope.xgos.portal.parameters.apikey.openroute;
        if (openroute && openroute.trim() != '') {
          return 'openroute';
        } else {
          const google = $rootScope.xgos.portal.parameters.apikey.google;
          if (google && google.trim() != '') {
            return 'google';
          }
        }
      }
    }
    return {
      GoogleMapsFactory: GoogleMapsFactory,
      lazyLoad: lazyLoad,
      coordinatesToLatLng: coordinatesToLatLng,
      latLngTocoordinates: latLngTocoordinates,
      setDragableLayers: setDragableLayers,
      getInformationsFromCoordinates: getInformationsFromCoordinates,
      getInformationsFromAddress: getInformationsFromAddress,
      getElevationFromOpenRoute: getElevationFromOpenRoute,
      typeOfApiUsed: typeOfApiUsed,
    };
  };
  GoogleMapsFactory.$inject = [
    '$window',
    '$q',
    '$rootScope',
    '$http',
    'gaJsUtils',
    '$filter',
  ];
  return GoogleMapsFactory;
});
