'use strict';
define(function() {
  var EditFactory = function(
    $http,
    gaUrlUtils,
    $q,
    $location,
    $rootScope,
    $filter, gcRestrictionProvider
  ) {
    var Edit = {};
    /**
     * Class : Edit
     * Factory WebServices
     */
    function historicize(fid, senddata, crs) {
      console.log(senddata);
      var promise = $http.post(
        '/services/{portalid}/edit/' + fid + '/historicize?f=json&crs=' + crs,
        senddata
      );
      promise.then(
        function(res) {
          console.log(res);
          // service level logic if any
        },
        function(err) {
          console.log(err);
        }
      );
      return promise;
    }

    function depose(fid, senddata, crs) {
      console.log(senddata);
      var promise = $http.post(
        '/services/{portalid}/edit/' + fid + '/depose?f=json&crs=' + crs,
        senddata
      );
      promise.then(
        function(res) {
          console.log(res);
          // service level logic if any
        },
        function(err) {
          console.log(err);
        }
      );
      return promise;
    }

    var QueryDataDefers = [];

    function createDefer(defer) {
      var int = Math.round(Math.random() * 10e7);
      QueryDataDefers.push({
        idx: int,
        defer: defer,
      });
      return int;
    }

    function dataResultAndroid(res, int) {
      var defer;
      try {
        var index;
        for (var i = 0; i < QueryDataDefers.length; i++) {
          var d = QueryDataDefers[i];
          if (d.idx === int) {
            defer = d.defer;
            index = i;
            break;
          }
        }

        var response = {
          data: res,
        };
        try {
          if (response.data && typeof response.data == 'string') {
            response.data = JSON.parse(response.data);
          }
        } catch (e) {
          console.log(response.data);
          e.stack;
        }
        defer.resolve(response);
      } catch (e) {
        e.stack;
        defer.reject();
      }
      QueryDataDefers.splice(index, 1);
    }

    /**
     * Function: applyedits
     */
    function applyedits(fid, idstodelete, senddata, crs, checktopology) {
      console.log(senddata);
      if (typeof EditAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        EditAndroid.add(fid, JSON.stringify(senddata), int);
        return defer.promise;
      } else {
        var promise = $http.post(
          '/services/{portalid}/edit/' +
            fid +
            '/applyedits?f=json&crs=' +
            crs +
            '&checktopology=' +
            checktopology +
            '&ids=' +
            idstodelete,
          senddata
        );
        promise.then(
          function() {
            // service level logic if any
          },
          function(err) {
            console.log(err);
          }
        );
        return promise;
      }
    }

    /**
     * Function: add
     */
    function add(fid, senddata, crs, checktopology, applyRules, returnInCrsProj) {
      console.log(senddata);
      if (typeof EditAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        EditAndroid.add(fid, JSON.stringify(senddata), int);
        return defer.promise;
      } else {
        senddata.features = senddata.features.map(transformFeatureForSave);
        var promise = $http.post(
          '/services/{portalid}/edit/' +
            fid +
            '/add?f=json&crs=' +
            crs +
            (checktopology ? '&checktopology=' + checktopology : '') +
            (applyRules ? '&applyRules=true' : '') +
            (returnInCrsProj ? '&returnInCrsProj=true' : ''),
          senddata
        );
        promise.then(
          function() {
            // service level logic if any
          },
          function(err) {
            console.log(err);
          }
        );
        return promise;
      }
    }

    /**
     * Function: specialUpdate
     */
    function specialUpdate(fid, senddata, crs, checktopology, applyRules) {
      console.log(senddata);
      var promise = $http.post(
        '/services/{portalid}/edit/' +
          fid +
          '/specialUpdate?f=json&crs=' +
          crs +
          '&checktopology=' +
          checktopology +
          (applyRules ? '&applyRules=true' : ''),
        senddata
      );
      promise.then(
        function() {
          // service level logic if any
        },
        function(err) {
          console.log(err);
        }
      );
      return promise;
    }

    /* Function: delete_feature_relations **/
    function delete_feature_relations(fid, featdUid, feataUid, featdFid) {
      var promise = $http.get(
        '/services/{portalid}/edit/{fid}/rel/delete_feature_relations?f=json' +
          '&fid=' +
          fid +
          '&featdUid=' +
          featdUid +
          '&feataUid=' +
          feataUid +
          '&featdFid=' +
          featdFid
      );

      return promise;
    }
    /**
     * Function: delete
     */
    function remove(fid, ids, allData) {
      if (typeof EditAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        EditAndroid.delete(fid, ids, int);
        return defer.promise;
      } else {
        ids = gaUrlUtils.encodeUriQuery(ids || '');
        var app = '';
        if ($location.search().app) {
          app = $location.search().app;
        } else {
          try {
            app = angular.module('gcMain').app;
          } catch (e) {
            console.log('no app name available');
          }
        }
        var promise = $http.get(
          '/services/{portalid}/edit/' +
            fid +
            '/delete?f=json' +
          (allData ? ('&allData=' + true) : ('&ids=' + ids)) +
            '&appname=' + app
        );
        promise.then(function() {
          // service level logic if any
        });
        return promise;
      }
    }

    /**
     * Function: deletewhere
     */
    function deleteWhere(fid, where) {
      where = gaUrlUtils.encodeUriQuery(where || '');
      var app = '';
      if ($location.search().app) {
        app = $location.search().app;
      } else {
        try {
          app = angular.module('gcMain').app;
        } catch (e) {
          console.log('no app name available');
        }
      }
      var promise = $http.get(
        '/services/{portalid}/edit/' + fid + '/deleteWhere?f=json' +
        '&fid=' + fid +
        '&where=' + where +
        '&appname=' + app
      );

      return promise;
    }
    /**
     * Function: update
     */
    function update(fid, senddata, crs) {
      if (typeof EditAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        EditAndroid.update(fid, JSON.stringify(senddata), int);
        return defer.promise;
      } else {
        senddata.features = senddata.features.map(transformFeatureForSave);
        var promise = $http.post(
          '/services/{portalid}/edit/' + fid + '/update?f=json&crs=' + crs,
          senddata
        );
        promise.then(function(res) {
          var ind;
          if (res.data.errors.length != 0) {
            for (ind = 0; ind < res.data.errors.length; ind++) {
              require('toastr').error(
                $filter('translate')('editfactory.' + res.data.errors[ind])
              );
            }
          }
        },
        result => {
          gcRestrictionProvider.showDetailsErrorMessage(result);
        });
        return promise;
      }
    }

    /**
     * Function: updatewhere
     */
    function updateWhere(fid, where, senddata) {
      where = gaUrlUtils.encodeUriQuery(where || '');
      var promise = $http.post(
        '/services/{portalid}/edit/' +
          fid +
          '/updateWhere?f=json' +
          '&where=' +
          where,
        senddata
      );

      return promise;
    }


    /**
     * Function: updatespecificproperties
     */
    function updatespecifiedproperties(fid, senddata, crs) {
      var promise = $http.post(
        '/services/{portalid}/edit/' +
          fid +
          '/updateSpecifiedProperties?f=json&crs=' +
          crs,
        senddata
      );

      return promise;
    }

    /**
     * Function: r_add
     */
    function r_add(senddata, fid, idd, relname) {
      var promise = $http.post(
        '/services/{portalid}/edit/' +
          fid +
          '/rel/' +
          idd +
          '/' +
          relname +
          '/add?f=json',
        senddata
      );

      return promise;
    }

    /**
     * Function: r_delete
     */
    function r_delete(fid, relname, ids, delrobject) {
      ids = gaUrlUtils.encodeUriQuery(ids || '');
      //            var promise = $http.get('/services/{portalid}/edit/{fid}/rel/{idd}/{relname}/delete?f=json' +'&fid=' + fid +'&relname=' + relname +'&ids=' + ids +'&delrobject=' + delrobject);
      var promise = $http.get(
        '/services/{portalid}/edit/' +
          fid +
          '/rel/' +
          relname +
          '/delete?f=json' +
          '&fid=' +
          fid +
          '&relname=' +
          relname +
          '&idd=' +
          ids +
          '&delrobject=' +
          delrobject
      );
      promise.then(function(res) {});
      return promise;
    }

    /**
     * Function: r_delete_1_nm
     *    Supprime la relation entre 2 objets précis.
     *    La relation est déduité du feaid qui est dans le path
     *    et de son nom passé en paramètre.
     */
    function r_delete_1_nm(fid, relname, idd, ida, delrobject) {
      var promise = $http.get(
        '/services/{portalid}/edit/' +
          fid +
          '/rel/' +
          relname +
          '/delete_nm?f=json' +
          '&idd=' +
          idd +
          '&idaList=' +
          ida +
          '&delrobject=' +
          delrobject
      );

      return promise;
    }

    /**
     * Function: updatebyid
     */
    function updatebyid(fid, ids, fieldname, fieldtype, fieldvalue) {
      ids = gaUrlUtils.encodeUriQuery(ids || '');
      var promise = $http.get(
        '/services/{portalid}/edit/' +
          fid +
          '/updateById?f=json' +
          '&fid=' +
          fid +
          '&ids=' +
          ids +
          '&fieldname=' +
          fieldname +
          '&fieldtype=' +
          fieldtype +
          '&fieldvalue=' +
          fieldvalue
      );

      return promise;
    }
    /**
     * Function: updateexpression
     */
    function updateexpression(senddata, fid) {
      var promise = $http.post(
        '/services/{portalid}/edit/' + fid + '/updateExpression?f=json',
        senddata
      );

      return promise;
    }
    /**
     * Function: updatebyid
     */
    function updatebyfilter(fid, where, fieldname, fieldtype, fieldvalue) {
      var promise = $http.post(
        '/services/{portalid}/edit/' +
          fid +
          '/updateByFilter?f=json' +
          '&fid=' +
          fid +
          '&fieldname=' +
          fieldname +
          '&fieldtype=' +
          fieldtype +
          '&fieldvalue=' +
          fieldvalue,
        where
      );

      return promise;
    }

    function transformFeatureForSave(feature) {
      feature.properties = Object.keys(feature.properties || {})
        .reduce((properties, key) => {
          if (
            typeof feature.properties[key] === 'object' &&
            feature.properties[key] !== null &&
            typeof feature.properties[key].getMonth === 'function'
          ) {
            properties[key] = moment(feature.properties[key]).utc().format('YYYY-MM-DDTHH:mm:ss.SSSZZ');
          } else {
            properties[key] = feature.properties[key];
          }
          return properties;
        }, {});
      return feature;
    }
    return {
      Edit: Edit,
      historicize: historicize,
      depose: depose,
      applyedits: applyedits,
      add: add,
      specialUpdate: specialUpdate,
      remove: remove,
      update: update,
      deleteWhere: deleteWhere,
      r_add: r_add,
      updatespecifiedproperties: updatespecifiedproperties,
      r_delete: r_delete,
      r_delete_1_nm: r_delete_1_nm,
      updatebyid: updatebyid,
      updateWhere: updateWhere,
      updateexpression: updateexpression,
      delete_feature_relations: delete_feature_relations,
      dataResultAndroid: dataResultAndroid,
      updatebyfilter: updatebyfilter,
    };
  };
  EditFactory.$inject = [
    '$http',
    'gaUrlUtils',
    '$q',
    '$location',
    '$rootScope',
    '$filter', 'gcRestrictionProvider'
  ];
  return EditFactory;
});
