'use strict';
define(function () {
  var BacAppFactory = function (
    $http,
    $location,
    ConfigFactory,
    $q,
    FeatureTypeFactory,
    gaUrlUtils,
    $rootScope,
    $filter,
    gaDomUtils,
    gaJsUtils,
    $sce,
    UsersFactory,
    QueryFactory,
    CommonFactory,
    PortalsFactory
  ) {
    var appCfg = {};

    /*----------------------------------------------------------------
         initdatabase
         ----------------------------------------------------------------*/
    function initappCfg(cfg) {
      appCfg = cfg;
    }

    /**
     * Function: initdatabase
     */
    function initdatabase(appname) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/{appname}/initDatabase?f=json' +
          '&appname=' +
          appname
      );

      return promise;
    }

    /**
     * Function: checkbacappdata
     */

    function checkbacappdata() {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/checkBacAppData?f=json'
      );
      return promise;
    }

    /*----------------------------------------------------------------
         dossier
         ----------------------------------------------------------------*/
    var getDossierCanceler = $q.defer();
    var getDossierResolved = false;
    var getDossierCancel = function () {
      getDossierCanceler.resolve('http call aborted');
    };
    /**
     * Function: getdossiers
     */
    function getdossiers(
      filtre_controle,
      where,
      crs,
      page,
      count,
      liaison_filter,
      case_sensitive,
      sort,
      restrict_ids,
      isExport
    ) {
      if (getDossierResolved) getDossierCancel();

      let dateNow = Date.now();

      getDossierCanceler = $q.defer();
      getDossierResolved = isExport !== true;

      // edit filtre alerte
      const myRegexp = /alerte ILIKE '%(.*?)%'/g;
      const match = myRegexp.exec(where);
      dateNow = $filter('date')(dateNow, 'yyyy-MM-ddT00:00:00.000Z');
      if (match != null) {
        console.log(match);
        let toReplace;
        let needUpdate = false;
        switch (match[1]) {
          case 'sans':
            toReplace = "alerte IS NULL OR alerte = '' ";
            needUpdate = true;
            break;
          case 'alerte':
            toReplace =
              "alerte IS NOT NULL AND alerte <> '' AND alerte_echeance IS NULL";
            needUpdate = true;
            break;
          case 'echeance':
            toReplace = 'alerte_echeance IS NOT NULL';
            needUpdate = true;
            break;
          case 'alerte_verte':
            toReplace =
              'alerte_echeance IS NOT NULL AND alerte_echeance AFTER ' +
              $filter('date')(
                gaJsUtils.addDays(dateNow, appCfg.main.dossierCfg.alerte.green),
                'yyyy-MM-ddT00:00:00.sssZ'
              ) +
              '';
            needUpdate = true;
            break;
          case 'alerte_jaune':
            toReplace =
              'alerte_echeance IS NOT NULL AND alerte_echeance AFTER ' +
              $filter('date')(
                gaJsUtils.addDays(dateNow, appCfg.main.dossierCfg.alerte.red),
                'yyyy-MM-ddTHH:mm:ss.sssZ'
              ) +
              ' AND alerte_echeance BEFORE ' +
              $filter('date')(
                gaJsUtils.addDays(dateNow, appCfg.main.dossierCfg.alerte.green),
                'yyyy-MM-ddTHH:mm:ss.sssZ'
              ) +
              '';
            needUpdate = true;
            break;
          case 'alerte_rouge':
            toReplace =
              'alerte_echeance IS NOT NULL AND alerte_echeance BEFORE ' +
              $filter('date')(
                gaJsUtils.addDays(dateNow, appCfg.main.dossierCfg.alerte.red),
                'yyyy-MM-ddTHH:mm:ss.sssZ'
              ) +
              '';
            needUpdate = true;
            break;
        }
        if (needUpdate) where = where.replace(match[0], toReplace);
      }

      where = gaUrlUtils.encodeUriQuery(where || '');
      sort = sort || '';
      restrict_ids = restrict_ids || '';
      if (liaison_filter === '{}') liaison_filter = '';
      if (typeof ancAppAndroid !== 'undefined') {
        /*var res = {
                    data : ancAppAndroid.getDossiers("anc", filtre_controle,
                                                  where,
                                                 crs,   page,
                                                  count,
                                                   liaison_filter,// filtre de liaison avec d'autre composant (exemple personne)
                                                  case_sensitive,
                                                  sort,
                                                  restrict_ids)
                };

                console.log(res.data);
                if ( res.data ){
                    res.data = JSON.parse(res.data);
                    getDossierCanceler.resolve(res);
                } else {
                    getDossierCanceler.resolve(res);
                }*/
        ancAppAndroid.getDossiers(
          'bac',
          filtre_controle,
          where,
          crs,
          page,
          count,
          liaison_filter, // filtre de liaison avec d'autre composant (exemple personne)
          case_sensitive,
          sort,
          restrict_ids
        );
        return getDossierCanceler.promise;
      } else {
        liaison_filter = encodeURI(liaison_filter);
        let promise = $http({
          method: 'GET',
          url:
            '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getDossiers?f=json&filtre_controle=' +
            filtre_controle +
            '&where=' +
            where +
            '&crs=' +
            crs +
            '&page=' +
            page +
            '&count=' +
            count +
            '&liaison_filter=' +
            liaison_filter +
            '&case_sensitive=' +
            case_sensitive +
            '&sort=' +
            sort +
            '&restrict_ids=' +
            restrict_ids +
            '&isExport=' +
            (isExport === true),
          timeout: getDossierCanceler.promise,
        });
        promise.then(function (res) {
          // service level logic if any
          getDossierResolved = false;
        });
        return promise;
      }
    }

    function sendResultBackDossiers(result) {
      const res = {
        data: undefined,
      };
      if (result) {
        try {
          res.data = JSON.parse(result.split('__KIS__').join('"'));
        } catch (e) {
          console.log(result.split('__KIS__').join('"'));
          e.stack;
        }
        getDossierCanceler.resolve(res);
      } else {
        getDossierCanceler.resolve(res);
      }
    }

    /**
     * Function: getdossier_villes
     */
    function getdossier_villes() {
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        let defer = $q.defer();
        const int = createDefer(defer);
        ancAppAndroid.getDossier_villes(int);
        return defer.promise;
      } else {
        const promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getDossier_villes?f=json'
        );
        return promise;
      }
    }

    /**
     * Function: getdossier
     */
    function getdossier(id_dossier) {
      if (typeof ancAppAndroid !== 'undefined') {
        let defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.getDossier(id_dossier, int);
        return defer.promise;
      } else {
        if (angular.isArray(id_dossier)) id_dossier = id_dossier.split(',');
        const promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getDossier?f=json&id_dossier=' +
            id_dossier
        );
        return promise;
      }
    }

    /**
     * Function: getdossierbycontroleid
     */
    function getdossierbycontroleid(id_controle) {
      if (typeof ancAppAndroid !== 'undefined') {
        let defer = $q.defer();
        const int = createDefer(defer);
        ancAppAndroid.getDossierByControleId(id_controle, int);
        return defer.promise;
      } else {
        const promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getDossierByControleId?f=json&id_controle=' +
            id_controle
        );
        return promise;
      }
    }

    /**
     * Function: adddossier
     */
    function adddossier(senddata, appName) {
      console.log(senddata)
      appName = appName || appCfg.appname;
      const promise = $http.post(
        '/services/{portalid}/bacapp/' + appName + '/addDossier?f=json',
        senddata
      ) 
      
      return promise;
    }

    /**
     * Function: checkdossiersamereference
     */
    function checkdossiersamereference(senddata, appName) {
      appName = appName || appCfg.appname;
      const promise = $http.post(
        '/services/{portalid}/bacapp/' +
          appName +
          '/checkDossierSameReference?f=json',
        senddata
      );
      return promise;
    }

    /**
     * Function: updatedossier
     */
    function updatedossier(senddata) {
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        let defer = $q.defer();
        const int = createDefer(defer);
        ancAppAndroid.updateDossier(JSON.stringify(senddata), int);
        return defer.promise;
      } else {
        const promise = $http.post(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/updateDossier?f=json',
          senddata
        );
        return promise;
      }
    }

    /**
     * Function: updatestatutdossiers
     */
    function updatestatutdossiers(id_dossiers, statut) {
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        let defer = $q.defer();
        const int = createDefer(defer);
        ancAppAndroid.updateStatutDossiers(id_dossiers, statut, int);
        return defer.promise;
      } else {
        const promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/updateStatutDossiers?f=json&id_dossiers=' +
            id_dossiers +
            '&statut=' +
            statut
        );
        promise.then((res) => {
          // service level logic if any
        });
        return promise;
      }
    }

    /*----------------------------------------------------------------
         Personnes
         ----------------------------------------------------------------*/
    /**
     * Function: getpersonnes
     */
    function getpersonnes(appname, where) {
      /**/
      where = where || '1=1';
      if (typeof ancAppAndroid !== 'undefined') {
        let defer = $q.defer();
        const int = createDefer(defer);
        ancAppAndroid.getPersonnes(int);
        return defer.promise;
      } else {
        const promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getPersonnes?f=json' +
            '&appname=' +
            appname +
            '&where=' +
            where
        );
        return promise;
      }
    }
    /**
     * Function: getpersonne
     */
    function getpersonne(id_personne) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.getPersonne(id_personne, int);
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getPersonne?f=json&id_personne=' +
            id_personne
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

     /**
     * Function : get the id of the last personne added
     */
      const getIdLastPersonneAdded = (adresse_pays, nom, civilite, adresse_cp, adresse_rue, adresse_ville,prenom) => {
        return  $http.post(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
              '/getIdLastPersonneAdded?f=json&adresse_pays='
            + adresse_pays + '&nom=' + nom + '&civilite=' + civilite + '&adresse_cp=' + adresse_cp
            + '&adresse_rue=' + adresse_rue +  '&adresse_rue=' + adresse_rue
            + '&adresse_ville=' + adresse_ville + '&prenom=' + prenom
        ).catch(
            (error) => {
              if (error.data && typeof error.data === 'string') {
                console.error(error.data);
              }
            }
        );
      };
    /**
     * Function: addpersonne
     */
    function addpersonne(senddata,type,idDossier,UpdateOrCreate) {
      //@BACAPP
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var response = {
          data: undefined,
        };
        var value;
        var val = ancAppAndroid.addPersonne(JSON.stringify(senddata));
        try {
          value = JSON.parse(val);
        } catch (e) {
          e.stack;
          value = val;
        }
        response.data = value;
        defer.resolve(response);
        return defer.promise;
      } else {
        var promise = $http.post(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/addPersonne?f=json'+ '&type=' + type + '&idDossier=' + idDossier + '&UpdateOrCreate='+ UpdateOrCreate,
          senddata
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

    /**
     * Function: updatepersonne
     */
    function updatepersonne(senddata) {
      //@BACAPP
      /*var promise = $http.post('/services/{portalid}/bacapp/' + appCfg.appname + '/updatePersonne?f=json', senddata);
            promise.then(function (res) {
                // service level logic if any
            });
            return promise;*/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var response = {
          data: undefined,
        };
        var value;
        var val = ancAppAndroid.updatePersonne(JSON.stringify(senddata));
        try {
          value = JSON.parse(val);
        } catch (e) {
          value = val;
        }
        response.data = value;
        defer.resolve(response);
        return defer.promise;
      } else {
        var promise = $http.post(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/updatePersonne?f=json&bacapp=' +
            (appCfg.appname || ''),
          senddata
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

    /*----------------------------------------------------------------
         Parcelles
         ----------------------------------------------------------------*/
    /**
     * Function: getparcelles
     */
    function getparcelles(id_dossier) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.getParcelles(int);
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getParcelles?f=json' +
            '&where=' +
            id_dossier
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

    /**
     * Function: getparcelle
     */
    function getparcelle(id_parcelle) {
      //@BACAPP
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.getParcelle(id_parcelle, int);
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getParcelle?f=json&id_parcelle=' +
            id_parcelle
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

    /**
     * Function: checkparcellealreadyused
     */
    function checkparcellealreadyused(type, ref_dossier, id_parcelle) {
      //@BACAPP
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.checkParcelleAlreadyUsed(
          type,
          ref_dossier,
          id_parcelle,
          int
        );
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/checkParcelleAlreadyUsed?f=json&type=' +
            type +
            '&ref_dossier=' +
            ref_dossier +
            '&id_parcelle=' +
            id_parcelle
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

    /**
     * Function: addparcelletodossier
     */
    function addparcelletodossier(type, ref_dossier, id_parcelle) {
      //@BACAPP
      /**/

      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.addParcelleToDossier(type, ref_dossier, id_parcelle, int);
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/addParcelleToDossier?f=json&type=' +
            type +
            '&ref_dossier=' +
            ref_dossier +
            '&id_parcelle=' +
            id_parcelle
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

    /**
     * Function: removeparcellefromdossier
     */
    function removeparcellefromdossier(type, ref_dossier, id_parcelle) {
      //@BACAPP

      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.removeParcelleFromDossier(
          type,
          ref_dossier,
          id_parcelle,
          int
        );
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/removeParcelleFromDossier?f=json&type=' +
            type +
            '&ref_dossier=' +
            ref_dossier +
            '&id_parcelle=' +
            id_parcelle
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

    /*----------------------------------------------------------------
         Dossiers <-> Personnes
         ----------------------------------------------------------------*/

    /**
     * Function: addpersonnetodossier
     */
    function addpersonnetodossier(
      type,
      ref_dossier,
      id_personne,
      dateDebutProprietaire,
      typeProp, 
      appName
    ) {
      
      //@BACAPP
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.addPersonneToDossier(type, ref_dossier, id_personne, int);
        return defer.promise;
      } else {
        appName = appName || appCfg.appname;
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appName +
            '/addPersonneToDossier?f=json' +
            '&type=' +
            type +
            '&ref_dossier=' +
            ref_dossier +
            '&id_personne=' +
            id_personne +
            (dateDebutProprietaire?
              '&dateDebutProprietaire=' +
              dateDebutProprietaire:'')+
            '&bacapp=true' +
            '&typeProp=' +
            typeProp
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

    /**
     * Function: removepersonneencoursfromdossier
     */
    function removepersonneencoursfromdossier(
      type,
      ref_dossier,
      id_personne,
      date_fin
    ) {
      date_fin = date_fin || '';
      //@BACAPP
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.removePersonneEnCoursFromDossier(
          type,
          ref_dossier,
          id_personne,
          date_fin,
          int
        );
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/removePersonneEnCoursFromDossier?f=json&type=' +
            type +
            '&ref_dossier=' +
            ref_dossier +
            '&id_personne=' +
            id_personne +
            '&date_fin=' +
            date_fin
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

    /**
     * Function: getancpersonne
     */
    function getancpersonne(id_personne) {
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var response = {
          data: undefined,
        };
        var value;
        var val = ancAppAndroid.getAncPersonne(id_personne);
        try {
          value = JSON.parse(val);
        } catch (e) {
          value = val;
        }
        response.data = value;
        defer.resolve(response);
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getAncPersonne?f=json' +
            '&id_personne=' +
            id_personne
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

    /**
     * Function: gethistopersonnesdossier
     */
    function gethistopersonnesdossier(type, ref_dossier) {
      //@BACPAPP
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.getHistoPersonnesDossier(type, ref_dossier, '', int);
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getHistoPersonnesDossier?f=json&type=' +
            type +
            '&ref_dossier=' +
            ref_dossier
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

    /**
     * Function: base64topng
     */
    function base64topng(senddata, fid) {
      var promise = $http.post(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/base64toPng?f=json' +
          '&fid=' +
          fid,
        senddata
      );

      return promise;
    }

    /*----------------------------------------------------------------
         Contrôles
         ----------------------------------------------------------------*/

    var QueryDataDefers = [];
    /**
     * Function: getcontroles
     */
    function getcontroles(dossier) {
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.getControles(dossier, int);
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getControles?f=json&dossier=' +
            dossier
        );
        promise
          .then(function (res) {
            console.log('res from bac factory', res);
            // service level logic if any
          })
          .catch((err) => {
            console.log('error controles from bac factory', err);
          });
        return promise;
      }
    }
    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);
        }
        defer.resolve(response);
      } catch (e) {
        if (defer != null) {
          defer.reject();
        }
      }
      QueryDataDefers.splice(index, 1);
    }
    /**
     * Function: addcontrole
     */
    function addcontrole(senddata, dossier, filiere_id) {
      filiere_id = filiere_id || '';
      if (typeof ancAppAndroid !== 'undefined') {
        const defer = $q.defer();
        const int = createDefer(defer);
        ancAppAndroid.addControle(
          dossier,
          filiere_id,
          JSON.stringify(senddata),
          int
        );
        return defer.promise;
      } else {
        const promise = $http.post(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/addControle?' +
            'dossier=' +
            dossier +
            '&filiere_id=' +
            filiere_id,
          senddata
        );
        promise.then((res) => {
          // service level logic if any
        });
        return promise;
      }
    }

    /**
     * Function: updatecontrole
     */
    function updatecontrole(senddata) {
      if (angular.isDefined(senddata.features[0])) {
        delete senddata.features[0].attachmentsNo;
      }

      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.updateControle(JSON.stringify(senddata), int);
        return defer.promise;
      } else {
        var promise = $http.post(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/updateControle?f=json',
          senddata
        );
        return promise;
      }
    }

    /**
     * Function: removecontrole
     */
    function removecontrole(dossier, controle, controle_type) {
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.removeControle(dossier, controle, controle_type, int);
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/removeControle?f=json' +
            '&dossier=' +
            dossier +
            '&controle=' +
            controle +
            '&controle_type=' +
            controle_type
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

    /**
     * Function: addcontroledetail
     */
    function addcontroledetail(senddata, dossiers, controle) {
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.addControleDetail(
          JSON.stringify(senddata),
          dossiers,
          controle,
          int
        );
        return defer.promise;
      } else {
        var promise = $http.post(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/addControleDetail?f=json' +
            '&dossiers=' +
            dossiers +
            '&controle=' +
            controle,
          senddata
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }
    /**
     * Function: getcontroledetail
     */
    function getcontroledetail(dossier, controle) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.getControleDetail(dossier, controle, '', int);
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getControleDetail?f=json&dossier=' +
            dossier +
            '&controle=' +
            controle
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

    /**
     * Function: getcontroledetailexterne
     */
    function getcontroledetailexterne(type) {
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.getControleDetailExterne(type, int);
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getControleDetailExterne?f=json&type=' +
            type
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }
    /**
     * Function: removecontroleexternedetail
     */
    function changeControleExterneDetail(
      filename,
      type,
      id_dossier,
      id_controle
    ) {
      id_dossier = id_dossier || '';
      id_controle = id_controle || '';
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.changeControleExterneDetail(
          filename,
          type,
          id_dossier,
          id_controle,
          int
        );
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/changeControleExterneDetail?f=json&filename=' +
            filename +
            '&type=' +
            type +
            '&id_dossier=' +
            id_dossier +
            '&id_controle=' +
            id_controle
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }
    /**
     * Function: activecontroledetailexterne
     */
    function activecontroledetailexterne(filename) {
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.activeControleDetailExterne(filename, int);
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/activeControleDetailExterne?f=json&filename=' +
            filename
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }

    function getCtrlFormCfg(ctrlType) {
      return ConfigFactory.get(
        'main',
        'bacFormCfg_' + ctrlType,
        appCfg.appname
      );
    }

    function getAllCtrlFormCfg() {
      return ConfigFactory.getAllFormCfg('bac', appCfg.appname);
    }

    /*----------------------------------------------------------------
         Factures
         ----------------------------------------------------------------*/

    /**
     * Function: generatefacturesdolibarr
     */
    function generatefacturesdolibarr(senddata) {
      var promise = $http.post(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/generateFacturesDolibarr?f=json',
        senddata
      );

      return promise;
    }

    /**
     * Function: getmontantfactures
     */
    function getmontantfactures(id_relation) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/getMontantFactures?f=json&id_relation=' +
          id_relation
      );

      return promise;
    }

    /**
     * Function: changestatutfactures
     */
    function changestatutfactures(factures, statut) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/changeStatutFactures?f=json&factures=' +
          factures +
          '&statut=' +
          statut
      );

      return promise;
    }
    /**
     * Function: uploaddashboarddoc
     */
    function uploaddashboarddoc(senddata, type) {
      var promise = $http.post(
        '/services/{portalid}/bacapp//uploaddashboarddoc?f=json' +
          '&type=' +
          type,
        senddata
      );

      return promise;
    }
    /**
     * Function: removedashboarddoc
     */
    function removedashboarddoc(type, fileName) {
      console.log('WHAT');
      var promise = $http.get(
        '/services/{portalid}/bacapp/removedashboarddoc?f=json' +
          '&type=' +
          type +
          '&fileName=' +
          fileName
      );

      return promise;
    }

    /**
     * Function: listdashboarddocs
     */
    function listdashboarddocs(type) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/listdashboarddocs?f=json' + '&type=' + type
      );

      return promise;
    }

    /**
     * Function: downloaddashboarddoc
     */
    function downloaddashboarddoc(type, name) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/downloaddashboarddoc?f=json' +
          '&type=' +
          type +
          '&name=' +
          name
      );

      return promise;
    }

    /**
     * Function: updatepersonhistory
     */
    function updatepersonhistory(senddata, type) {
      //@BACAPP
      var promise = $http.post(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/updatePersonHistory?f=json&type=' +
          type,
        senddata
      );

      return promise;
    }

    /**
     * Request the report generation and the export in pdf and jpeg
     * @param {type} jasperFileName
     * @param {type} jsonParameters
     * @returns {unresolved}
     */
    function generatereport(jasperFileName, jsonParameters) {
      var promise = $http.post(
        '/services/{portalid}/bacapp/generatereport' +
          '?jasperFileName=' +
          jasperFileName +
          '&dataStoreName=' +
          appCfg.main.datastore,
        '' + JSON.stringify(jsonParameters)
      );

      return promise;
    }

    /**
     * Function: getreportpdf
     */
    function getreportpdf(filename) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/getreportpdf?f=json' +
          '&filename=' +
          filename
      );

      return promise;
    }

    /**
     * Function: imprimerfactures
     */
    function imprimerfactures(senddata) {
      var promise = $http.post(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/imprimerFactures?f=json',
        senddata
      );

      return promise;
    }

    /**
     * Function: getfacturespdf
     */
    function getfacturespdf(senddata) {
      var promise = $http.post(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/getFacturesPDF?f=json',
        senddata
      );

      return promise;
    }

    /**
     * getControlesHTML
     */
    function getControlesHTML(ctrlName) {
      let g = $q.defer();

      const baseurl =
        $location.absUrl().split('#')[0] +
        'js/XG/widgets/bacapp/main/views/controle/';

      let promise = $http.get(baseurl + ctrlName + '/files.json');
      promise.then(
        (res) => {
          let files = res.data.files;
          for (let i in files) {
            files[i].template = ctrlName + '/' + files[i].template;
          }

          let mainLabel = ctrlName == 'Fiche_D' ? 'Contrôle' : 'Validation';
          files.push({
            template: ctrlName + '.html',
            label: mainLabel,
          });

          // retrieve all html
          const requests = [];
          for (let i in files) {
            requests.push(
              $http.get(baseurl + files[i].template, {
                cache: false,
              })
            );
          }

          $q.all(requests).then(
            (res) => {
              for (let x in res) {
                files[x].data = res[x].data;
                delete files[x].template;
              }
              g.resolve({ files: files });
            },
            () => {
              g.reject(files);
            }
          );
        },
        () => {
          g.reject();
        }
      );

      return g.promise;
    }

    /**
     * Function: getextractedjsondata
     */
    function getextractedjsondata(filename) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.getExtractedJsonData(filename, int);
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getExtractedJsonData?f=json&filename=' +
            filename
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }
    // return the url for the previous function, cause this is all we need to use it in docfeeder
    var getextractedjsondataurl = function (filename, apptype) {
      return (
        '/services/' +
        PortalsFactory.getPortalId() +
        '/bacapp/' +
        appCfg.appname +
        '/getExtractedJsonData?f=json&filename=' +
        filename +
        '&bacapp=' +
        apptype +
        '&token=' +
        gaUrlUtils.encodeUriQuery(localStorage.getItem('auth_token'))
      );
    };

    /**
     * Function: htmlformtojson
     */
    function htmlformtojson(senddata, name) {
      var promise = $http.post(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/htmlformtojson?f=json' +
          '&name=' +
          name,
        senddata
      );

      return promise;
    }

    /**
     * Function: create_controle_json_mapping_file
     */
    function create_controle_json_mapping_file(appname) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/create_controle_json_mapping_file?f=json'
      );

      return promise;
    }

    /**
     * Function: getmobileforms
     */
    function getmobileforms() {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/getMobileForms?f=json'
      );

      return promise;
    }

    /**
     * Function: getngincludeduhtml
     */
    function getngincludeduhtml(senddata) {
      var promise = $http.post(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/getNgIncludeDuHtml?f=json',
        senddata
      );

      return promise;
    }

    /**
     * Function: getzipdocumentstypes
     */
    function getZipDocumentsTypes(list_ids, list_names, pdf) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/getZipDocumentsTypes?f=json&list_ids=' +
          list_ids +
          '&list_names=' +
          list_names +
          '&pdf=' +
          pdf
      );

      return promise;
    }

    /**
     * Function: refreshnationalreglementaire
     */
    function refreshnationalreglementaire(appname) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/refreshNationalReglementaire?f=json' +
          '&appname=' +
          appname
      );

      return promise;
    }

    /**
     * Function: getreglementaire
     */
    function getreglementaire(filename) {
      /**/
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.getReglementaire(filename, int);
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getReglementaire?f=json&filename=' +
            filename
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }
    /**
     * Function: addreglementaire
     */
    function addreglementaire(senddata, filename, removeindex) {
      var promise = $http.post(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/addReglementaire?f=json' +
          '&filename=' +
          filename +
          '&removeindex=' +
          removeindex,
        senddata
      );

      return promise;
    }

    /**
     * Function: removereglementaire
     */
    function removereglementaire(filename, removeindex) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/removeReglementaire?f=json&filename=' +
          filename +
          '&removeindex=' +
          removeindex
      );

      return promise;
    }

    /**
     * Function: setindexation
     */
    function setindexation(appname) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/setIndexation?f=json'
      );

      return promise;
    }

    /**
     * Function: indexcontroles
     */
    function indexcontroles(appname) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/indexControles?f=json'
      );

      return promise;
    }

    /**
     * Function: addtournee
     */
    function addtournee(senddata) {
      var promise = $http.post(
        '/services/{portalid}/bacapp/' + appCfg.appname + '/addTournee?f=json',
        senddata
      );

      return promise;
    }

    /**
     * Function: gettournee
     */
    function gettournee(agent) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/getTournee?f=json&agent=' +
          agent
      );

      return promise;
    }

    /**
     * Function: getMobileTournee
     */
    function getMobileTournee(agent, tournee) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/getMobileTournee?f=json&agent=' +
          agent +
          '&tournee=' +
          tournee
      );

      return promise;
    }

    /**
     * Function: getMobileTournee
     */
    function getMobileTourneeProgression(agent, tournee) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/getMobileTourneeProgression?f=json&agent=' +
          agent +
          '&tournee=' +
          tournee
      );

      return promise;
    }

    /**
     * getBuildedFakeCtrlReponseFtiForElasticSearch
     * Retourne le fakeFti deja builde
     * @param {*} obj
     * @param {*} type
     */
    function getBuildedFakeCtrlReponseFtiForElasticSearch(type) {
      var g = $q.defer();
      g.resolve(extractedFormHtmlJsonData[type].fakeFti);
      return g.promise;
    }

    /**
     * buildFakeCtrlReponseFtiForElasticSearch
     * @param {*} obj
     * @param {*} res
     */
    function buildFakeCtrlReponseFtiForElasticSearch(obj, res) {
      let fakeCtrlReponseFti = {
        name: 'kis_bac_dossier_controle_reponse',
        alias: obj.label_court,
        ctrlType: obj.type,
        isCtrlReponse: true,
        attributes: [],
      };

      if (res.data.parts && res.data.parts.length > 0) {
        res.data.parts.map(function (part) {
          if (part.data && Array.isArray(part.data) && part.data.length > 0) {
            part.data.map((x) => {
              if (
                Object.keys(x).indexOf('description') !== -1 &&
                x.description
              ) {
                fakeCtrlReponseFti.attributes.push({
                  alias: x.description,
                  name: x.key.replace('cdata.', ''),
                  type: getServerDataType(x.type),
                  category: part.label,
                  prefixedAlias:
                    translateKeyForRecherche(x.key.replace('cdata.', '')) +
                    x.description,
                });
              }
            });
          }
        });
      }
      return fakeCtrlReponseFti;
    }

    let getServerDataType = (type) => {
      switch (type) {
        case 'date': {
          return 'java.sql.Timestamp';
        }
        case 'number': {
          return 'java.lang.Integer';
        }
        case 'checkbox': {
          return 'java.lang.Boolean';
        }
        default: {
          return 'java.lang.String';
        }
      }
    };

    let extractedFormHtmlJsonData = {};

    /**
     * getAllExtractedJsonData
     *  permet de ne requeter qu'une fois le contenu des fichiers html
     */
    var getAllExtractedJsonData = function () {
      var g = $q.defer();
      var controlesTypes = appCfg.main.controleCfg.map(function (x) {
        return x.type;
      });

      var getData = [];
      for (var i in controlesTypes) {
        getData.push(
          $http.get(getextractedjsondataurl(controlesTypes[i]), {
            cache: false,
          })
        );
      }

      $q.all(getData).then(
        function (res) {
          for (var i in appCfg.main.controleCfg) {
            extractedFormHtmlJsonData[appCfg.main.controleCfg[i].type] = {
              data: res[i],
              fakeFti: buildFakeCtrlReponseFtiForElasticSearch(
                appCfg.main.controleCfg[i],
                res[i]
              ),
            };
          }
          g.resolve();
        },
        function () {
          if ($rootScope.xgos.isroot) {
            require('toastr').warning(
              'Erreur lors de la récupération des contenus html des formulaires (getAllExtractedJsonData)',
              '',
              {
                positionClass: 'toast-bottom-left',
              }
            );
          }
          g.resolve();
        }
      );

      return g.promise;
    };

    /**
     * getAppCfg
     * @param cfgPromise
     * @param simpleGet - get the cfg only and no other check/redirection occurs
     * @param appname - specific appname
     */
    var watchUser;
    var bacDataChecked = false;
    function getAppCfg(cfgPromise, simpleGet, appname) {
      appCfg.appname = appname ? appname : $location.search().app;

      cfgPromise = cfgPromise || $q.defer();

      if (!simpleGet) {
        if (
          !~$location.path().indexOf('/bac/') ||
          !angular.isDefined($location.search().app)
        ) {
          $location.path('/404');
          cfgPromise.reject();
          return cfgPromise.promise;
        }
      }

      // be sure that auth is finished and user set before proceeding
      if (angular.isUndefined($rootScope.xgos.user)) {
        watchUser = $rootScope.$watch('xgos.user', function (u) {
          if (angular.isDefined(u)) {
            watchUser();
            return getAppCfg(cfgPromise);
          }
        });
      } else {
        // load only once
        if (angular.isDefined(appCfg.main)) {
          console.log('cfg already loaded');
          // @TODO RB stop here when in prod
          //return false;
        }

        var promise = ConfigFactory.get(
          'main',
          'mainConfig',
          appCfg.appname
        ).then(function (res) {
          appCfg.main = res.data;

          var needToUpdateCfg = false;

          // compatibilité ascendante
          if (angular.isDefined(appCfg.main.dashboardCfg)) {
            for (var i in appCfg.main.dashboardCfg) {
              if (!angular.isDefined(appCfg.main.dashboardCfg[i].type)) {
                appCfg.main.dashboardCfg[i].type = 'modele';
              }
            }
            needToUpdateCfg = 1;
          }

          if (!simpleGet) {
            if (appCfg.main == '') {
              $location.path('/bac/nocfg');
              $rootScope.$broadcast('resetBacNavigation');
              cfgPromise.resolve();
              return cfgPromise.promise;
            }

            if (!angular.isDefined(appCfg.main)) {
              appCfg.main = {};
              needToUpdateCfg = 1;
            }
            if (!angular.isDefined(appCfg.main.extra)) {
              appCfg.main.extra = {};
              needToUpdateCfg = 1;
            }

            // configuring parcelles is mandatory
            if (!appCfg.main.parcellesCfg || !appCfg.main.entreprisesCfg) {
              if ($location.path() != '/bac/admin/') {
                $location.path('/bac/admin');
                $rootScope.$broadcast('resetBacNavigation');
              }
            } else if (!appCfg.main.infosSass) {
              if ($location.path() != '/bac/admin') {
                $location.hash('sass');
                $location.path('/bac/admin/');
                $rootScope.$broadcast('resetBacNavigation');
              }
            }

            if (!appCfg.main.extra.infosSassListeVillesCfg) {
              appCfg.main.extra.infosSassListeVillesCfg = [];
              needToUpdateCfg = 1;
            }

            if (
              appCfg.main.extra.infosSassListeVillesCfg &&
              appCfg.main.extra.infosSassListeVillesCfg.length
            ) {
              var configVille = angular.copy(
                appCfg.main.extra.infosSassListeVillesCfg
              );
              appCfg.main.extra.infosSassListeVillesCfg = [];
              for (var i = 0; i < configVille.length; i++) {
                if (typeof configVille[i] == 'string') {
                  appCfg.main.extra.infosSassListeVillesCfg.push({
                    value: configVille[i],
                    cp: [],
                    pays: '',
                  });
                } else {
                  appCfg.main.extra.infosSassListeVillesCfg.push(
                    configVille[i]
                  );
                }
              }
            }

            if (!angular.isDefined(appCfg.main.properties)) {
              appCfg.main.properties = {};
              needToUpdateCfg = 1;
            }
            if (
              !angular.isDefined(
                appCfg.main.properties.gestionListesDeroulantes
              )
            ) {
              appCfg.main.properties.gestionListesDeroulantes = false;
              needToUpdateCfg = 1;
            }

            if (
              !angular.isDefined(
                appCfg.main.properties.setDateDebutPropObligatoire
              )
            ) {
              appCfg.main.properties.setDateDebutPropObligatoire = true;
              needToUpdateCfg = 1;
            }

            if (angular.isUndefined(appCfg.main.ddc)) {
              appCfg.main.ddc = {};
              appCfg.main.ddc.active = $location.search().operis;
              needToUpdateCfg = true;
            }

            if (
              angular.isDefined(appCfg.main.ddc.active) &&
              angular.isDefined($location.search().operis) &&
              appCfg.main.ddc.active != $location.search().operis
            ) {
              appCfg.main.ddc.active = $location.search().operis;
              needToUpdateCfg = true;
            }
            if (!angular.isDefined(appCfg.main.properties.dolibarr)) {
              appCfg.main.properties.dolibarr = {
                active: false,
              };
              needToUpdateCfg = 1;
            }

            if (
              !angular.isDefined(
                appCfg.main.properties.dolibarr.facturationTierce
              )
            ) {
              appCfg.main.properties.dolibarr.facturationTierce = {
                active: false,
                interface: {
                  type: '',
                },
              };
              needToUpdateCfg = 1;
            }

            if (!angular.isDefined(appCfg.main.properties.civilites)) {
              appCfg.main.properties.civilites = {
                liste: ['Monsieur', 'Madame'],
              };
              needToUpdateCfg = 1;
            }
            if (!angular.isDefined(appCfg.main.properties.gestionCivilites)) {
              appCfg.main.properties.gestionCivilites = false;
              needToUpdateCfg = 1;
            }

            if (!appCfg.main.properties.serviceLocalisationDossier) {
              appCfg.main.properties.serviceLocalisationDossier = {
                url: false,
                type: 'ban',
              };
              needToUpdateCfg = 1;
            }
            /**
             * Ajout de nouvelle properties , gcDataTableCount 
             * (nombre des lignes a afficher dans le tableau de la liste des dossiers)
             */
            if (!angular.isDefined(appCfg.main.properties.gcDataTableCount)) {
              appCfg.main.properties.gcDataTableCount = 10;
              needToUpdateCfg = 1;
            }

            if (!angular.isDefined(appCfg.main.properties.priseRdv)) {
              appCfg.main.properties.priseRdv = {
                active: true,
              };
              needToUpdateCfg = 1;
            }

            if (!appCfg.main.properties.extraFormFields) {
              appCfg.main.properties.extraFormFields = {
                fields: [],
              };
              needToUpdateCfg = 1;
            }

            if (
              !angular.isDefined(appCfg.main.properties.importDossiersExternes)
            ) {
              appCfg.main.properties.importDossiersExternes = {
                active: false,
                source: '',
              };
              needToUpdateCfg = 1;
            }

            if (!appCfg.main.controleCfg) {
              appCfg.main.controleCfg = [
                {
                  label:
                    "Demande de renseignements relatifs à l'assainissement",
                  label_court: 'Demande renseignements',
                  type: 'DR',
                  template: 'DR.html',
                  document_types: [],
                },
                {
                  label: "Demande d'autorisation d'urbanisme",
                  label_court: 'Autorisation urbanisme',
                  type: 'DAU',
                  template: 'DAU.html',
                  document_types: [],
                },
                {
                  label: 'Demande de branchement',
                  label_court: 'Branchement',
                  type: 'DB',
                  template: 'DB.html',
                  document_types: [],
                },
                {
                  label: 'Demande de conformité',
                  label_court: 'Conformité',
                  type: 'DC',
                  template: 'DC.html',
                  document_types: [],
                },
                {
                  label: 'Contrôle de conformité Industriel',
                  label_court: 'Contrôle Industriel',
                  type: 'CCI',
                  template: 'CCI.html',
                  document_types: [],
                },
                {
                  label: 'Autorisation de déversement',
                  label_court: 'Autorisation déversement',
                  type: 'AUD',
                  template: 'AUD.html',
                  document_types: [],
                },
              ];

              needToUpdateCfg = 1;
            }
            ConfigFactory.checkDocumentsForConfig(appCfg.main.controleCfg).then(
              function (res) {
                appCfg.main.controleCfg = res.data;
              }
            );

            if (!appCfg.main.controleWorkflowCfg) {
              appCfg.main.controleWorkflowCfg = [
                {
                  avec_delai: false,
                  current_controle: 'DR',
                  avis: 0,
                  next_controle: 'DAU',
                  delai: false,
                },
                {
                  avec_delai: false,
                  current_controle: 'DR',
                  avis: 1,
                  next_controle: 'DR',
                  delai: false,
                },
                {
                  avec_delai: false,
                  current_controle: 'DAU',
                  avis: 2,
                  next_controle: 'DB',
                  delai: false,
                },
                {
                  avec_delai: false,
                  current_controle: 'DAU',
                  avis: 3,
                  next_controle: 'DAU',
                  delai: false,
                },
                {
                  avec_delai: false,
                  current_controle: 'DB',
                  avis: 4,
                  next_controle: 'DC',
                  delai: false,
                },
                {
                  avec_delai: false,
                  current_controle: 'DB',
                  avis: 5,
                  next_controle: 'DB',
                  delai: false,
                },
                {
                  avec_delai: false,
                  current_controle: 'DC',
                  avis: 7,
                  next_controle: 'DC',
                  delai: false,
                },
              ];
              needToUpdateCfg = 1;
            }

            /*
                         facturationPeriodeCfg
                         */
            if (!appCfg.main.periodesCfg) {
              appCfg.main.periodesCfg = {
                periodes: [],
                tarification: [],
              };
              needToUpdateCfg = 1;
            } else {
              if (appCfg.main.periodesCfg.periodes) {
                for (
                  var i = 0;
                  i < appCfg.main.periodesCfg.periodes.length;
                  i++
                ) {
                  if (
                    !appCfg.main.periodesCfg.periodes[i].nom ||
                    appCfg.main.periodesCfg.periodes[i].nom == ''
                  ) {
                    appCfg.main.periodesCfg.periodes[i].nom = 'défaut';
                    needToUpdateCfg = 1;
                  }
                }
              }
            }

            // default map configuration
            if (!appCfg.main.mapConfiguration) {
              appCfg.main.mapConfiguration = {
                bbox: [
                  -703637.6010015747, 5258148.272161824, 1130851.0778426554,
                  6481140.724724644,
                ],
                featuresConfig: {
                  kis_bac_dossier: '1-1',
                },
              };
              needToUpdateCfg = 1;
            }

            //Dossier
            if (!appCfg.main.dossierCfg) {
              appCfg.main.dossierCfg = {
                numerotation: {
                  auto: false,
                  separator: '_',
                  parts: [
                    {
                      key: 'date',
                      format: 'ddMMyyyy',
                    },
                    {
                      key: 'index',
                    },
                    {
                      key: 'string',
                      format: 'dossier_bac',
                    },
                  ],
                },
                templates: [],
                extraColonne : {
                  active: false,
                  name: 'affectation_construction',
                },
              };

              needToUpdateCfg = 1;
            }
            if (!appCfg.main.dossierCfg.extraColonne) {
              appCfg.main.dossierCfg.extraColonne =  {
                  active: false,
                  name: 'affectation_construction',
                }
                needToUpdateCfg = 1;
            }

            if (!appCfg.main.dossierCfg.listeDossiers) {
              appCfg.main.dossierCfg.listeDossiers = {
                extra_colonnes: [],
              };
              needToUpdateCfg = 1;
            }

            if (!appCfg.main.demandeUrbanismeCfg) {
              appCfg.main.demandeUrbanismeCfg = [
                {
                  type: 'PC',
                  label: 'Permis de construire',
                  template: 'Fiche_1.html',
                },
                {
                  type: 'PA',
                  label: "Permis d'aménager",
                  template: 'Fiche_1.html',
                },
                {
                  type: 'DT',
                  label: 'Déclaration de travaux',
                  template: 'Fiche_1.html',
                },
                {
                  type: 'CU',
                  label: "Certificat d'urbanisme",
                  template: 'Fiche_2.html',
                },
                {
                  type: 'PD',
                  label: 'Permis de démolir',
                  template: 'Fiche_2.html',
                },
                {
                  type: 'PL',
                  label: 'Permis de lotir',
                  template: 'Fiche_2.html',
                },
              ];
              needToUpdateCfg = 1;
            }

            if (appCfg.main.entreprisesCfg) {
              if (
                !angular.isDefined(appCfg.main.entreprisesCfg.fields['actif'])
              ) {
                appCfg.main.entreprisesCfg.fields['actif'] = 'actif';
              }
              if (
                !angular.isDefined(appCfg.main.entreprisesCfg.fields['agree'])
              ) {
                appCfg.main.entreprisesCfg.fields['agree'] = 'agree';
              }

              var oldAddressField = false;
              for (var i in appCfg.main.entreprisesCfg.fields) {
                if (i == 'adresse') oldAddressField = true;
              }
              if (
                oldAddressField &&
                appCfg.main.entreprisesCfg.emplacement == 'kis_anc_entreprise'
              ) {
                delete appCfg.main.entreprisesCfg.fields['adresse'];
                [
                  'fax',
                  'adresse_num_rue',
                  'adresse_num_rue_extra',
                  'adresse_rue',
                  'adresse_ville',
                  'adresse_cp',
                  'adresse_bp',
                  'adresse_pays',
                  'adresse_batiment',
                  'adresse_appt',
                  'adresse_etage',
                  'adresse_escalier',
                  'adresse_complement',
                ].forEach(function (x) {
                  appCfg.main.entreprisesCfg.fields[x] = x;
                });
                needToUpdateCfg = 1;
              }
              if (
                oldAddressField &&
                appCfg.main.entreprisesCfg.emplacement != 'kis_anc_entreprise'
              ) {
                delete appCfg.main.entreprisesCfg;
                needToUpdateCfg = 1;
              }
            }

            // init des branches a afficher dans la partie gauche d'un dossier
            if (
              !appCfg.main.properties.branchToShow ||
              angular.isArray(appCfg.main.properties.branchToShow)
            ) {
              appCfg.main.properties.branchToShow = {
                general: {
                  visible: true,
                },
                demandes_urba: {
                  visible: true,
                },
                branchements: {
                  visible: true,
                },
                instructions: {
                  visible: true,
                },
                documents_dossier: {
                  visible: true,
                },
              };
              needToUpdateCfg = 1;
            }

            if (angular.isUndefined(appCfg.main.dossierCfg.alerte)) {
              appCfg.main.dossierCfg.alerte = {
                green: 31,
                red: 5,
              };
              needToUpdateCfg = 1;
            }

            if (!appCfg.main.dossierCfg.avisControles) {
              appCfg.main.dossierCfg.avisControles = [
                {
                  key: 0,
                  label: 'Favorable',
                  label_initial: 'Favorable',
                  default: true,
                  type_controle: 'DR',
                  actif: true,
                },
                {
                  key: 1,
                  label: 'Défavorable',
                  label_initial: 'Défavorable',
                  default: true,
                  type_controle: 'DR',
                  actif: true,
                },
                {
                  label: 'Favorable',
                  type_controle: 'DAU',
                  key: 2,
                  label_initial: 'Favorable',
                  default: false,
                  actif: true,
                },
                {
                  label: 'Défavorable',
                  type_controle: 'DAU',
                  key: 3,
                  label_initial: 'Défavorable',
                  default: false,
                  actif: true,
                },
                {
                  label: 'Favorable',
                  type_controle: 'DB',
                  key: 4,
                  label_initial: 'Favorable',
                  default: false,
                  actif: true,
                },
                {
                  label: 'Défavorable',
                  type_controle: 'DB',
                  key: 5,
                  label_initial: 'Défavorable',
                  default: false,
                  actif: true,
                },
                {
                  label: 'Favorable',
                  type_controle: 'DC',
                  key: 6,
                  label_initial: 'Favorable',
                  default: false,
                  actif: true,
                },
                {
                  label: 'Défavorable',
                  type_controle: 'DC',
                  key: 7,
                  label_initial: 'Défavorable',
                  default: false,
                  actif: true,
                },
              ];
            }
          }

          if (
            appCfg.main.parcellesCfg &&
            appCfg.main.parcellesCfg.fields &&
            !appCfg.main.parcellesCfg.fields.insee
          ) {
            appCfg.main.parcellesCfg.fields['insee'] = 'insee';
            needToUpdateCfg = 1;
          }

          if (needToUpdateCfg) {
            updateAppCfg(1);
          }
          appCfg.allowedtoopenanc = false 
          // is bac admin
          appCfg.isAdmin = $rootScope.xgos.isadmin;
          appCfg.hasAccess = {
            facturation: angular.copy($rootScope.xgos.isadmin),
            mapApp: angular.copy($rootScope.xgos.isadmin)
          };

          if (angular.isArray($rootScope.xgos.user.roles)) {
            for (var i in $rootScope.xgos.user.roles) {
              if ($rootScope.xgos.user.roles[i].name == 'BAC_admin') {
                appCfg.isAdmin = true;
                appCfg.hasAccess.mapApp = true;
              }
              if ($rootScope.xgos.user.roles[i].name == 'BAC_facturation') {
                appCfg.hasAccess.facturation = true;
              }  else if($rootScope.xgos.user.roles[i].name == 'consultation'){
                appCfg.hasAccess.mapApp = true
               }

              if ($rootScope.xgos.user.roles[i].name == 'ANCadmin' || $rootScope.xgos.user.roles[i].name == 'ANC_agent' || $rootScope.xgos.user.roles[i].name == 'ANC_responsable'){
                appCfg.allowedtoopenanc = true;
               }
            }
          }

          // needed data
          var neededData = [
            FeatureTypeFactory.get(),
            getAllExtractedJsonData(),
          ];

          $q.all(neededData).then(function (res) {
            // check bac data (equivalent to check portal data) only once per browser instance
            if (!bacDataChecked) {
              gaDomUtils.showGlobalLoader();
              extractModelFromForm();
              checkbacappdata().then(
                function (res) {
                  gaDomUtils.hideGlobalLoader();
                  cfgPromise.resolve();
                  $rootScope.$broadcast('BacAppCfgSet', {
                    cfg: appCfg,
                  });
                  bacDataChecked = true;
                },
                function () {
                  gaDomUtils.hideGlobalLoader();
                }
              );
            } else {
              cfgPromise.resolve();
              $rootScope.$broadcast('BacAppCfgSet', {
                cfg: appCfg,
              });
            }
          });
        });
      }

      return cfgPromise.promise;
    }

    /**
     * @param silent
     */
    var updateAppCfg = function (silent) {
      var promise = ConfigFactory.add(
        appCfg.main,
        'main',
        'mainConfig',
        appCfg.appname
      );
      promise.then(function () {
        if (!silent)
          require('toastr').success(
            "Configuration de l'application mise à jour",
            '',
            {
              positionClass: 'toast-bottom-left',
            }
          );
      });

      // on sauvegarde aussi, chaque jour, une version temporaire
      ConfigFactory.add(
        appCfg.main,
        'main',
        'mainConfig_' + moment(new Date()).format('DD_MM_YYYY'),
        appCfg.appname
      );

      return promise;
    };

    /**
     * Returen controle Display name
     * @param type string
     * @param date_creation date
     * @returns {string}
     */
    var getControleName = function (type, date_creation, shortname) {
      var label = '';
      shortname = shortname || 1;

      appCfg.main.controleCfg.forEach(function (x) {
        if (x.type == type) {
          label = shortname ? x.label_court : x.label;
        }
      });

      if (angular.equals({}, date_creation)) date_creation = false;

      return (
        label +
        ' ' +
        (date_creation
          ? ' - ' + $filter('date')(date_creation, 'dd.MM.yy')
          : '')
      );
    };

    /**
     * Génération du numéro auto de dossier
     * @param id
     * @param numerotation
     */
    var getNumeroAuto = function (id, numerotation) {
      var partsPreview = [];
      if (!numerotation) numerotation = appCfg.main.dossierCfg.numerotation;

      numerotation.parts.forEach(function (p) {
        var displayValue = id;
        if (p.key != 'index') {
          if (p.key == 'string') displayValue = p.format;
          if (p.key == 'date')
            displayValue = $filter('date')(new Date(), p.format);
        }
        partsPreview.push(displayValue);
      });
      return partsPreview.join(numerotation.separator);
    };

    /**
     * transform bacDossier to Dossier feature
     * in order to sumbit it to the server
     */
    var bacDossierToDossier = function (ancdossier, tmpReference) {
      var dossier = angular.copy(ancdossier);

      if (tmpReference) {
        dossier.properties.ref_dossier = tmpReference;
      }

      delete dossier.properties.proprietaires;
      delete dossier.properties.locataires;
      delete dossier.properties.demandeurs;
      delete dossier.properties.parcelleHabitation;
      delete dossier.properties.parcelleFiliere;
      delete dossier.properties.parcelleHabitation_numero;
      delete dossier.properties.parcelleHabitation_section;
      delete dossier.properties.adresse;
      delete dossier.properties.dernierControle;
      delete dossier.properties.prochainControle;
      delete dossier.properties.adresse_rue_complement;
      delete dossier.properties.etablissement;
      delete dossier.properties.activite_secondaire;
      delete dossier.properties.activite_principale;
      delete dossier.properties.details_icpe;

      if (angular.isDefined(appCfg.main.dossierCfg.listeDossiers)) {
        appCfg.main.dossierCfg.listeDossiers.extra_colonnes.map(function (x) {
          var k = 'extrafilter_' + x.origine.fti + '_____' + x.origine.attr;
          delete dossier.properties[k];
        });
      }

      // transforme la geometrie en multipoints si pas deja le cas
      if (angular.isDefined(dossier.geometry) && dossier.geometry !== null) {
        console.log(dossier.geometry);
        if (dossier.geometry.type == 'Point') {
          dossier.geometry.type = 'MultiPoint';
          dossier.geometry.coordinates = [
            angular.copy(dossier.geometry.coordinates),
          ];
        }
      }

      return dossier;
    };

    /**
     * getNewControleData
     * @param id_dossier
     * @param controlesDuDossier
     * @param newCtrlType
     */
    var getNewControleData = function (
      dossier,
      controlesDuDossier,
      newCtrlType,
      oldControle
    ) {
      let newCtrlData = {};
      const id_dossier = dossier.id;
      const g = $q.defer();
      let dernierCtrl, prevCtrlType, commonKeys;
      if (!controlesDuDossier || !controlesDuDossier.length) {
        g.resolve(false);
      } else {
        if (oldControle) {
          dernierCtrl = oldControle;
          prevCtrlType = dernierCtrl.properties.type;
          commonKeys = [];
        } else {
          dernierCtrl = controlesDuDossier[0];
          if (isDcControle(newCtrlType)) {
            dernierCtrl = controlesDuDossier.find(controle => controle.properties.type === newCtrlType) || 
              dernierCtrl;
          }
          prevCtrlType = dernierCtrl.properties.type;
          commonKeys = [];
        }

        // get both json extractions
        var requests;
        if (typeof ancAppAndroid !== 'undefined') {
          requests = [
            getextractedjsondata(prevCtrlType),
            getextractedjsondata(newCtrlType),
          ];
        } else {
          requests = [
            $http.get(getextractedjsondataurl(prevCtrlType), {
              cache: false,
            }),
            $http.get(getextractedjsondataurl(newCtrlType), {
              cache: false,
            }),
          ];
        }

        // get all data

        $q.all(requests)
          .then(res => {
            if (oldControle || !isDcControle(newCtrlType)) { return res; }
            return prefillDcControleWithDossier(dossier, newCtrlData).then(controle => {
              newCtrlData = controle;
              return res;
            }).catch(() => res);
          })
          .then((res) => {
            // unique list of keys
            const extractKeys = (uns) => {
              var arrKeys = uns.data.parts.map(function (x) {
                return x.data.map(function (xx) {
                  return xx.key;
                });
              });
              return Array.prototype.concat
                .apply([], arrKeys)
                .filter(function (label) {
                  return angular.isDefined(label);
                });
            };
              // both arrays
            const prevModel = extractKeys(res[0]);
            const newModel = extractKeys(res[1]);

            if (newModel.length) {
              newModel.forEach(function (newKey) {
                if (~prevModel.indexOf(newKey))
                  commonKeys.push(newKey.replace('cdata.', ''));
              });
            }

            getcontroledetail(id_dossier, dernierCtrl.id).then(
              function (res) {
                if (angular.isDefined(res.data) && res.data != '') {
                  const oldCtrlData = res.data;
                  if (isDcControle(newCtrlType)) {
                    const hiddenParts = [
                      'info_generales.date_controleprecedent',
                      'branchement',
                      'boite_branchement',
                      'installation_eu',
                      'installation_ep',
                      'evacuation_eu',
                      'evacuation_ep'
                    ];
                    commonKeys = commonKeys.concat(hiddenParts);
                  }
                  if (angular.isDefined(res.data.datesDossier)) {
                    if (angular.isDefined(res.data.datesDossier.date_avis))
                      delete res.data.datesDossier.date_avis;
                    if (
                      angular.isDefined(
                        res.data.datesDossier.date_avis_controleur
                      )
                    )
                      delete res.data.datesDossier.date_avis_controleur;
                  }

                  for (let i in commonKeys) {
                    const oldvalue = gaJsUtils.checkNestedProperty(
                      commonKeys[i],
                      oldCtrlData
                    );
                    if (oldvalue || oldvalue === 0) {
                      gaJsUtils.setNestedProperty(
                        commonKeys[i],
                        newCtrlData,
                        oldvalue
                      );
                    }
                  }
                }

                const notNeededProperties = [
                  'reference_daact',
                  'datesDossier.date_controle',
                  'datesDossier.date_rdv',
                  'general.condition_meteo',
                  'general.statut_rdv',
                  'conformite',
                  'datesDossier.date_avis',
                  'datesDossier.date_avis_controleur'
                ];
                notNeededProperties.forEach(propertyKey => {
                  gaJsUtils.removeNestedProperty(propertyKey, newCtrlData);
                });
                g.resolve(newCtrlData);
              },
              function () {
                g.resolve(false);
              }
            );
          },
          function (x) {
            g.resolve(false);
          }
        );
      }

      return g.promise;
    };

    /**
     * extract ngmodels from html forms and create files
     * _extract
     * @param ctrl
     */
    var _extract = function (ctrl) {
      var p = $q.defer();

      // get ctrl main file
      var ctrlName = ctrl.template.replace('.html', '');
      getControlesHTML(ctrlName).then(
        function (res) {
          htmlformtojson(res, ctrl.type).then(
            function () {
              p.resolve();
            },
            function () {
              p.reject();
            }
          );
        },
        function () {
          // require('toastr').error("Une erreur s'est produite lors de la récupération données du formulaire " + ctrlName + ".");
          console.log(
            "Une erreur s'est produite lors de la récupération données du formulaire " +
              ctrlName +
              '.'
          );
          p.reject();
          //gaDomUtils.hideGlobalLoader();
        }
      );

      return p.promise;
    };

    /**
     * extractModelFromForm
     * recursive _extract (launched once per session, @TODO handle it better)
     * @param idx
     */
    var extractModelFromForm = function (idx) {
      if (!idx) idx = 0;

      //appCfg.main.properties.derniere_extraction_formulaires = moment(new Date()).format('DD-MM-YYYY');
      //updateAppCfg(1);

      if (angular.isDefined(appCfg.main.controleCfg[idx])) {
        _extract(appCfg.main.controleCfg[idx]).then(function () {
          extractModelFromForm(idx + 1);
        });
      }
    };
    /**
     * Function: synchrotournee
     */
    function synchrotournee(tournee, id) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/synchroTournee?f=json&tournee=' +
          tournee +
          '&id=' +
          id
      );

      return promise;
    }

    /**
     * Function: synchrotournee
     */
    function synchroTourneeProgression(uid) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/synchroTourneeProgression?f=json&uid=' +
          uid
      );

      return promise;
    }
    /**
     * Function: synchrotournee
     */
    /*function synchrotournee(appname , tournee) {
            var promise = $http.get('/services/{portalid}/bacapp/{appname}/synchroTournee?f=json' +'&appname=' + appname +'&tournee=' + tournee);
            promise.then(function(res){
                // service level logic if any
            });
            return promise;
        };*/
    /**
     * Function: removetournee
     */
    function removetournee(idtournee) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/removeTournee?f=json&idtournee=' +
          idtournee
      );

      return promise;
    }
    /**
     * Function: debloquetournee
     */
    function debloquetournee(idtournee, bool) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/debloqueTournee?f=json&idtournee=' +
          idtournee +
          '&bool=' +
          bool
      );

      return promise;
    }
    function debloqueDossier(id) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/debloqueDossier?f=json&id=' +
          id
      );
      promise.then(
        function (res) {
          // service level logic if any
        },
        function () {}
      );
      return promise;
    }
    /**
     * Function: removetournee
     */
    /*function removetournee(appname , tournee) {
            var promise = $http.get('/services/{portalid}/bacapp/{appname}/removeTournee?f=json' +'&appname=' + appname +'&tournee=' + tournee);
            promise.then(function(res){
                // service level logic if any
            });
            return promise;
        };*/
    /**
     * Function: gettournees
     */
    function gettournees(agent) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/getTournees?f=json&agent=' +
          agent
      );

      return promise;
    }
    /**
     * Function: gettournees
     */
    function getAllTournees(agent) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/getAllTournees?f=json&agent=' +
          agent
      );

      return promise;
    }
    /**
     * Function: gettournees
     */
    function getDossiersTournee(id) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/getDossiersTournee?f=json&id=' +
          id
      );

      return promise;
    }

    /*******************************************************************************************
     *******************************************************************************************
     *******************************************************************************************
     *******************************************************************************************
     *
     *
     *
     *  SPECIFIQUE BAC
     *
     *
     *
     *******************************************************************************************
     *******************************************************************************************
     *******************************************************************************************
     ******************************************************************************************/

    /**
     * Function: addobjetbranchementtodossier
     */
    function addobjetbranchementtodossier(senddata) {
      var promise = $http.post(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/addObjetBranchementToDossier?f=json',
        senddata
      );

      return promise;
    }
    /**
     * Function: adddemandeurbanisme
     */
    function adddemandeurbanisme(senddata, id_dossier) {
      var promise = $http.post(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/addDemandeUrbanisme?f=json' +
          '&id_dossier=' +
          id_dossier,
        senddata
      );

      return promise;
    }
    /**
     * Function: removedemandeurbanisme
     */
    function removedemandeurbanisme(id_demande_urbanisme, id_dossier, type) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/removeDemandeUrbanisme?f=json&id_demande_urbanisme=' +
          id_demande_urbanisme +
          '&id_dossier=' +
          id_dossier +
          '&type=' +
          type
      );

      return promise;
    }

    /**
     * Function: updatedemandeurbanisme
     */
    function updatedemandeurbanisme(senddata, id_dossier) {
      var promise = $http.post(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/updateDemandeUrbanisme?f=json' +
          '&id_dossier=' +
          id_dossier,
        senddata
      );

      return promise;
    }
    /**
     * Function: getdemandeurbanisme
     */
    function getdemandeurbanisme(dossier) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        return defer.promise;
      } else {
        var promise = $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
            '/getDemandeUrbanisme?f=json&dossier=' +
            dossier
        );
        promise.then(function (res) {
          // service level logic if any
        });
        return promise;
      }
    }
    /**
     * Function: addcaracteristiqueconstruction
     */
    function addcaracteristiqueconstruction(
      senddata,
      id_demande_urbanisme,
      id_dossier
    ) {
      var promise = $http.post(
        '/services/{portalid}/bacapp/{appname}/addCaracteristiqueConstruction?f=json' +
          '&id_demande_urbanisme=' +
          id_demande_urbanisme +
          '&id_dossier=' +
          id_dossier,
        senddata
      );

      return promise;
    }

    /**
     * Function: getcaracteristiqueconstruction
     */
    function getcaracteristiqueconstruction(appname, id_demande_urbanisme) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/{appname}/getCaracteristiqueConstruction?f=json' +
          '&appname=' +
          appname +
          '&id_demande_urbanisme=' +
          id_demande_urbanisme
      );

      return promise;
    }

    var getChoixStatutRDV = () => {
      return [
        {
          value: 'absent',
          label: 'Absent',
        },
        {
          value: 'refus',
          label: 'Refus de visite',
        },
        {
          value: 'npai',
          label: "N'habite pas à l'adresse indiquée",
        },
        {
          value: 'present',
          label: 'Présent',
        },
        {
          value: 'reporte',
          label: 'Reporté',
        },
        {
          value: 'annule',
          label: 'Annulé',
        },
      ];
    };

    let getListeDossiersCfg = (dossierFti) => {
      // attributes
      let dossierAttributes = [
        {
          name: 'etablissement',
          type: 'java.lang.String',
          filterType: 'liaison',
        },
        {
          name: 'proprietaires',
          key: 'nomComplet',
          type: 'ObjectsArray',
          filterType: 'liaison',
        },
        {
          name: 'locataires',
          key: 'nomComplet',
          type: 'ObjectsArray',
          filterType: 'liaison',
        },
        {
          name: 'parcelleHabitation_numero',
          type: 'java.lang.String',
          filterType: 'liaison',
        },
        {
          name: 'parcelleHabitation_section',
          type: 'java.lang.String',
          filterType: 'liaison',
        },
        {
          name: 'adresse_cp',
          type: 'java.lang.String',
        },
        {
          name: 'adresse_ville',
          type: 'java.lang.String',
        },
      ];

      const dossierAttributesProprietaires = [
        {
          name: 'numRueProprietaire',
          alias: 'N° rue propriétaire',
          type: 'java.lang.Integer',
          filterType: 'liaison',
          csvValueInfo:['numRue', 'numRueExtra'],
          parentPropertyName:'proprietaires'
        },
        {
          name: 'rueProprietaire',
          alias: 'Rue',
          type: 'java.lang.String',
          filterType: 'liaison',
          csvValueInfo:['rue'],
          parentPropertyName:'proprietaires'
        },
        {
          name: 'villeProprietaire',
          alias: 'Ville ',
          type: 'java.lang.String',
          filterType: 'liaison',
          csvValueInfo:['ville'],
          parentPropertyName:'proprietaires'
        },
        {
          name: 'cpProprietaire',
          alias: 'CP ',
          type: 'java.lang.String',
          filterType: 'liaison',
          csvValueInfo:['cp'],
          parentPropertyName:'proprietaires'
        },
        {
          name: 'paysProprietaire',
          alias: 'Pays',
          type: 'java.lang.String',
          filterType: 'liaison',
          csvValueInfo:['pays'],
          parentPropertyName:'proprietaires'
        },
        {
          name: 'typeProprietaire',
          alias: 'Type',
          type: 'java.lang.String',
          filterType: 'liaison',
          csvValueInfo:['typeProprietaire'],
          parentPropertyName:'proprietaires'
        },
      ];
      let positionDecalage = 0 ;
      if (dossierFti != null) {
        dossierFti.attributes.forEach((att) => {
          if (
            ~[
              'alerte',
              'ref_dossier',
              'adresse_num_rue',
              'adresse_rue',
              'type_dernier_controle',
              'date_dernier_controle',
              'avis_dernier_controle',
              'date_prochain_controle',
              'prochain_controle',
              'affectation_construction'
            ].indexOf(att.name)
          ) {
            if (att.name === 'ref_dossier') {
              dossierAttributes.splice(0, 0, att);
            } else if (att.name === 'alerte') {
              dossierAttributes.splice(0, 0, att);
            } else if (
              appCfg.main.dossierCfg.extraColonne.active == true &&
              att.name === 'affectation_construction'
            ) {
              dossierAttributes.splice(2, 0, att);
              positionDecalage = positionDecalage +1 ;
              $rootScope.hasnotExtra = false;
              $rootScope.hasExtra = true;
            } else if (att.name === 'adresse_num_rue') {
              dossierAttributes.splice(6+positionDecalage, 0, att);
            } else if (att.name === 'adresse_rue') {
              let rueComplement = {
                type: att.type,
                name: 'adresse_rue_complement',
                alias: att.alias,
              };
              dossierAttributes.splice(7+positionDecalage, 0, rueComplement);
            } else if (att.name === 'type_dernier_controle') {
              dossierAttributes.push(att);
            } else if (att.name !== 'affectation_construction') {
              dossierAttributes.push(att);
            }
          }
        });
        dossierAttributesProprietaires.forEach((att) => {
          dossierAttributes.push(att);
        });
      }

      let renduTitleColonneDossier = {
        avis_dernier_controle: (v, notHTml) => {
          if(notHTml){
            return 'Avis/Statut';
          } else {
            const str = '<span class="spanEtatDossier">Avis/Statut</span>';
            return v ? $sce.trustAsHtml(str) : v;
          }
        },
        date_dernier_controle: (v) => {
          return v ? $sce.trustAsHtml('Date Dernière instruction') : v;
        },
        adresse_cp: (v) => {
          return 'CP';
        },
        type_dernier_controle: (v, notHTml) => {
          if (notHTml){
            return 'Dernière instruction';
          } else {
            const str = '<span>Dernière instruction</span>';
            return v ? $sce.trustAsHtml(str) : v;
          }
        },
        type_prochain_controle: (v, notHtml) => {
          if (notHtml){
            return 'Prochaine instruction';
          } else {
            const str = '<span>Prochaine instruction</span>';
            return v ? $sce.trustAsHtml(str) : v;
          }
        },
        prochain_controle: (v, notHtml) => {
          if (notHtml) {
            return 'Prochaine instruction';
          } else {
            const str = '<span>Prochaine instruction</span>';
            return v ? $sce.trustAsHtml(str) : v;
          }
        },
        date_prochain_controle: (v) => {
          const str = 'Date préconisée';
          return v ? $sce.trustAsHtml(str) : v;
        },
        numRueProprietaire: (v) => {
          return v ? $sce.trustAsHtml('N° rue propriétaire') : v;
        },
        rueProprietaire: (v) => {
          return v ? $sce.trustAsHtml('Rue') : v;
        },
        villeProprietaire: (v) => {
          return v ? $sce.trustAsHtml('Ville') : v;
        },
        cpProprietaire: (v) => {
          return v ? $sce.trustAsHtml('CP') : v;
        },
        paysProprietaire: (v) => {
          return v ? $sce.trustAsHtml('Pays') : v;
        },
      };

      if (angular.isDefined(appCfg.main.dossierCfg.listeDossiers)) {
        appCfg.main.dossierCfg.listeDossiers.extra_colonnes.map((x) => {
          const pos = x.position ? x.position : 0;
          const k = 'extrafilter_' + x.origine.fti + '_____' + x.origine.attr;
          // add attr
          dossierAttributes.splice(pos, 0, {
            name: k,
            type: 'java.lang.String',
            filterType: 'liaison',
          });
          // titre de la colonne
          renduTitleColonneDossier[k] = (v) => {
            return x.alias;
          };
        });
      }

      const controle_filter = [];
      appCfg.main.controleCfg.forEach((item) => {
        controle_filter.push({
          key: item.type,
          label: item.label_court,
        });
      });
      controle_filter.unshift({
        key: '',
        label: 'Toutes instructions confondues',
      });

      const typeDerCtrlFilter = {
        cfg: {
          multiSelect: true,
        },
        liste: controle_filter,
      };
      typeDerCtrlFilter.cfg.dependency = {
        field: 'avis_dernier_controle',
        thisDepField: 'key',
        otherDepField: 'type_controle',
        showAnyWay: [
          {
            field: 'type_controle',
            value: 'Statut du RDV',
          },
        ],
      };

      const liste_ville_filter = [];
      getdossier_villes().then((res) => {
        res.data.forEach((v) => {
          const v_upper = v.charAt(0).toUpperCase() + v.slice(1);
          liste_ville_filter.push({
            key: v,
            label: v_upper,
          });
        });
        liste_ville_filter.unshift({
          key: '',
          label: 'Toutes villes confondues',
        });
      });

      const liste_type_proprio_filter = [];
      liste_type_proprio_filter.push({
        key: '1',
        label: 'Entreprise',
      });
      liste_type_proprio_filter.push({
        key: '2',
        label: 'Particulier',
      });
      liste_type_proprio_filter.push({
        key: '3',
        label: 'Sociéte',
      });
      liste_type_proprio_filter.push({
        key: '99',
        label: 'Autre',
      });
      liste_type_proprio_filter.push({
        key: '',
        label: 'Tous types confondus',
      });

      // prepare filtre sur les statuts/avis
      const copyAvisCtrl = [];
      const choixTmp = getChoixStatutRDV();
      for (let i in choixTmp) {
        copyAvisCtrl.push({
          label: choixTmp[i].label,
          type_controle: 'Statut du RDV',
        });
      }
      const inactiveAvis = [];
      for (let j in appCfg.main.dossierCfg.avisControles) {
        let avisControle = appCfg.main.dossierCfg.avisControles[j];
        if (
          angular.isDefined(avisControle.type_controle) ||
          avisControle.actif === true
        ) {
          copyAvisCtrl.push(avisControle);
        } else {
          let avisControleCopy = angular.copy(avisControle);
          avisControleCopy.type_controle = 'Avis inactifs';
          inactiveAvis.push(avisControleCopy);
        }
      }
      copyAvisCtrl.unshift({
        key: '',
        label: 'Tous avis confondus',
      });
      if (inactiveAvis.length) {
        inactiveAvis.forEach((avisControle) => copyAvisCtrl.push(avisControle));
      }

      // liste des agents
      var agentsPortail = [];
      UsersFactory.getactiveuserslight().then((res) => {
        const gusers = res.data;
        let _users;
        if (typeof userAndroid !== 'undefined') {
          _users = gusers;
        } else {
          _users = gusers.filter((u) => {
            return ['BAC_agent'].filter((n) => {
              return (
                u.roles
                  .map((g) => {
                    return g.name;
                  })
                  .indexOf(n) !== -1
              );
            }).length;
          });
        }
        for (let i in _users) {
          agentsPortail.push({
            key: _users[i].login,
            label: _users[i].login,
          });
        }
        agentsPortail.unshift({
          key: null,
          label: 'Tous agents confondus',
        });
      });

      const tableNextControlNameAndAgentBAC = (controlType, dossier, notHtml) => {
        let controlHtml = CommonFactory.replaceControlName(controlType,
          false, appCfg.main.controleCfg);
        if (typeof ancAppAndroid !== 'undefined') {
          controlHtml =
            '<span class="listeDossierCtrlType" ng-click="actionFromDatatable({fn:\'openBacControle\',data:{dossierId: \'' +
            dossier.id +
            '\'}})">' +
            controlHtml +
            ' ' +
            '</span>';
        } else {
          controlHtml =
            '<span class="listeDossierCtrlType" ng-click="actionFromDatatable({fn:\'openBacControle\',data:{dossierId: \'' +
            dossier.id +
            "', controleId: '" +
            dossier.properties.dernierControle.id +
            '\'}})">' +
            controlHtml +
            ' ' +
            '</span>';
        }

        let agent = '';
        if (
          gaJsUtils.checkNestedProperty(
            'properties.dernierControle.agent',
            dossier
          )
        ) {
          agent = notHtml
            ? (dossier.properties.dernierControle.agent || '')
            :'<span class="text-muted"><i class="fa fa-user"></i><small> ' +
            (dossier.properties.dernierControle.agent || '') +
              '</small></span>';
        }

        return (notHtml
          ? CommonFactory.findControlTypeLabel(controlType, appCfg.main.controleCfg)
          + (dossier.properties.dernierControle.agent || '')
          : $sce.trustAsHtml(controlHtml + ' ' + agent));
      };

      const tableControlAndAgentForLastControlBAC =  (controlType, dossier, notHtml) => {
        let controlName = CommonFactory.replaceControlName(controlType,
          false, appCfg.main.controleCfg);
        let htmlValue = '';
        if (typeof ancAppAndroid !== 'undefined') {
          htmlValue =
            '<span class="listeDossierCtrlType" ng-click="actionFromDatatable({fn:\'openBacControle\',data:{dossierId: \'' +
            dossier.id +
            '\'}})">' +
            controlName +
            ' ' +
            '</span>';
        } else {
          htmlValue =
            '<span class="listeDossierCtrlType" ng-click="actionFromDatatable({fn:\'openBacControle\',data:{dossierId: \'' +
            dossier.id +
            "', controleId: '" +
            dossier.properties.dernierControle.id +
            '\'}})">' +
            controlName +
            ' ' +
            '</span>';
        }

        let agent = '';
        if (
          gaJsUtils.checkNestedProperty(
            'properties.dernierControle.agent',
            dossier
          )
        ) {
          agent = notHtml
            ? (dossier.properties.dernierControle.agent || '')
            :'<span class="text-muted"><i class="fa fa-user"></i><small> ' +
            (dossier.properties.dernierControle.agent || '') +
            '</small></span>';
        }

        return (notHtml
          ? CommonFactory.findControlTypeLabel(controlType, appCfg.main.controleCfg)
          + (agent ? ' ' + agent : '')
          : $sce.trustAsHtml(htmlValue + ' ' + agent));
      };

      const tableParcelleHabitation = (x, dossier, notHtml) => {
        if (notHtml){
          return (x ? gaJsUtils.getTextFromHtmlString(x) :'');
        } else {
          return (x ? $sce.trustAsHtml(x.replace(/\n/g, '<br>')) : '');
        }
      };
      const date_prochain_controle_preconise = (
        crudValue,
        dossier,
        notHtml
      ) => {
        let value = crudValue;


        let newValueToDetermine ='<div class="tableTdWrapperPickDate"><span class="spanEtatDossierDate spanEtatDossierNoDatePreconisee '
          + ' datePrecoDatePicker"><div class="spanEtatDosssierDate-inner"> '
          + '<i class="fa fa-edit"></i> <input title="Cliquer pour'
          + ' éditer" type="text"  ng-model="obj.properties[att.name]"'
          + ' data-autoclose="1" name="date" date-type="string" data-date-format="dd/MM/yyyy" model-date-format="yyyy-MM-ddTHH:mm:ss.sssZ" autocomplete="off"'
          + ' ng-change="actionFromDatatable({fn:\'updateDatePreconiseeBac\',data:{obj: obj}})" bs-datepicker>'
          + '</div></span>'
          + '</div>';

          newValueToDetermine = $sce.trustAsHtml(newValueToDetermine);

        if (value) {
          value = new Date(value);
          let today = new Date();
          let ndays = Math.round(
            (value.valueOf() - today.valueOf()) / 1000 / 86400 - 0.5
          );
          value = $filter('date')(value, 'dd-MM-yyyy');
          let _xclass;
          if (ndays < 0) {
            _xclass = 'spanEtatDossierAlert';
          } else if (ndays < 30 && ndays >= 0) {
            _xclass = 'spanEtatDossierWarning';
          } else {
            _xclass = 'spanEtatDossierValid';
          }
          value = notHtml
            ? value
            : '<div class="tableTdWrapperPickDate"><span class="spanEtatDossierDate '
            + _xclass
            + ' datePrecoDatePicker"><div class="spanEtatDosssierDate-inner"> '
            + '<i class="fa fa-edit"></i> <input title="Cliquer pour'
            + ' éditer" type="text"  ng-model="obj.properties[att.name]"'
            + ' data-autoclose="1" name="date" data-type="date"'
            + ' ng-change="actionFromDatatable({fn:\'updateDatePreconiseeBac\',data:{obj: obj}})" bs-datepicker>'
            + '</div></span>'
            + '</div>';

          value = $sce.trustAsHtml(value);
        }
        return value || newValueToDetermine;
      };
      return {
        attributes: dossierAttributes,
        renduTitleColonneDossier: renduTitleColonneDossier,
        renduColonnesEtatDossier: {
          alerte: (crudValue, dossier, notHtml) => CommonFactory.tableAlert(crudValue, dossier, notHtml, appCfg.main.dossierCfg.alerte),
          etat_dossier: CommonFactory.tableStatus,
          adresse_num_rue: CommonFactory.tableAddressNumber,
          etablissement: (v, dossier) => {
            let value = '';
            if (
              dossier &&
              dossier.properties &&
              dossier.properties.etablissement &&
              dossier.properties.etablissement.nom
            ) {
              value = dossier.properties.etablissement.nom;
            }
            return value;
          },
          parcelleHabitation_numero: tableParcelleHabitation,
          parcelleHabitation_section: tableParcelleHabitation,
          type_dernier_controle: tableControlAndAgentForLastControlBAC,
          prochain_controle: tableNextControlNameAndAgentBAC,
          avis_dernier_controle: CommonFactory.lastControlAvis,
          date_prochain_controle: date_prochain_controle_preconise,
          date_dernier_controle: CommonFactory.date_dernier_controle,
          numRueProprietaire:  CommonFactory.numRueProprietaire,
          villeProprietaire: CommonFactory.villeProprietaire,
          paysProprietaire:  CommonFactory.paysProprietaire,
          rueProprietaire: CommonFactory.rueProprietaire,
          cpProprietaire: CommonFactory.cpProprietaire,
          typeProprietaire: CommonFactory.typeProprietaire,
          affectation_construction: CommonFactory.affectationConstruction,
        },
        filterRender: {
          alerte: [
            {
              key: 'sans',
              label: 'Sans',
            },
            {
              key: 'alerte',
              label: 'Alerte sans échéance',
            },
            {
              key: 'alerte_verte',
              label: 'Alerte verte',
              type: 'date',
            },
            {
              key: 'alerte_jaune',
              label: 'Alerte jaune',
              type: 'date',
            },
            {
              key: 'alerte_rouge',
              label: 'Alerte rouge',
              type: 'date',
            },
            {
              key: 'echeance',
              label: 'Alerte avec échéance',
            },
          ],
          etat_dossier: [
            {
              key: '',
              label: 'Tous états confondus',
            },
            {
              key: 'ouvert',
              label: 'Ouvert',
            },
            {
              key: 'en_cours',
              label: 'En cours',
            },
            {
              key: 'sans_suite',
              label: 'Sans suite',
            },
            {
              key: 'archive',
              label: 'Archivé',
            },
          ],
          avis_dernier_controle: {
            liste: copyAvisCtrl,
            groupBy: 'type_controle',
            cfg: { multiSelect: true },
          },
          prochain_controle: controle_filter,
          type_dernier_controle: typeDerCtrlFilter,
          adresse_ville: liste_ville_filter,
          typeProprietaire: liste_type_proprio_filter,
        },
        extraFilterRender: {
          type_dernier_controle: {
            liste: agentsPortail,
            key: 'agent_dernier_controle',
          },
          alerte: {
            key: 'alerte_search',
            type: 'string_search',
            symbol: '',
          },
        },
        editButton: [
          {
            type: 'component',
            config: {
              name: 'button',
              click: ['crud_update'],
            },
            cfg: {
              icon: { name: 'pencil-square-o' },
              iconOrLabel: 'icon',
              size: 'btn-xs',
              style: 'btn-default cursorHelp',
              title: 'Editer le dossier',
            },
          },
        ],
      };
    };


    //récupération de classe CSS a appliquer
    const getAlerteColorClass = (dateEcheance) => CommonFactory.getAlerteColorClass(dateEcheance, appCfg.main.dossierCfg.alerte);

    /**
     * translateKeyForRecherche
     * permet de prefixer les attributs des ctrl avec une sous-categorie (proprietaire, occupant, demandeur, service...) pour les select de recherche elastic
     * @param {*} key
     */
    let translateKeyForRecherche = function (key) {
      let t = '';

      // in case of cdata.cdata.
      key = key.replace('cdata.', '');
      if (!key.indexOf('info_generales.dossier.')) t = 'Dossier';
      if (!key.indexOf('info_generales.parcelleHabitation.'))
        t = 'Parcelle habitation';
      if (!key.indexOf('info_generales.parcelleFiliere.'))
        t = 'Parcelle filière';
      if (!key.indexOf('info_generales.proprietaire.')) t = 'Propriétaire';
      if (!key.indexOf('info_generales.locataire.')) t = 'Occupant';
      if (!key.indexOf('info_generales.demandeur.')) t = 'Demandeur';
      if (!key.indexOf('service_controle.')) t = 'Service de contrôle';
      if (!key.indexOf('conformite.')) t = 'Bloc avis';
      if (!key.indexOf('caracteristiques_hab.')) t = 'Habitation';

      if (!key.indexOf('general.concepteur.')) t = 'Concepteur';
      if (!key.indexOf('caracteristiques_terrain.')) t = 'Terrain';
      if (!key.indexOf('caracteristique_terrain.')) t = 'Terrain';
      if (!key.indexOf('pedo.')) t = 'Pédologie';
      if (!key.indexOf('etudes_doc.')) t = 'Etude de définition';
      if (!key.indexOf('caracteristiques_install.')) t = 'Installation';
      if (!key.indexOf('impact_filiere.')) t = 'Impact Filière';
      if (!key.indexOf('conc.')) t = 'Filière conforme ?';
      if (!key.indexOf('grille.')) t = 'Grille de conformité';

      if (!key.indexOf('donnee_controle.')) t = 'Général';
      if (!key.indexOf('general.')) t = 'Général';
      if (!key.indexOf('donnees_gen.')) t = 'Général';
      if (!key.indexOf('donnee_generale.')) t = 'Général';
      if (!key.indexOf('implant.')) t = 'Implantation';
      if (!key.indexOf('controle_implantation.')) t = 'Implantation';
      if (!key.indexOf('datesDossier.')) t = 'Date';
      if (!key.indexOf('avis_controle.')) t = 'Avis Contrôle';
      if (!key.indexOf('ponc.')) t = 'Ponctuel';
      if (!key.indexOf('modif.')) t = 'Modification';
      if (!key.indexOf('general.installateur.')) t = 'Installateur';

      // BAC
      if (!key.indexOf('info_ass_coll.')) t = 'Infos Ass. Coll.';
      if (!key.indexOf('info_generales.pers_present.')) t = 'Personne présente';
      if (!key.indexOf('info_generales.certificat_urbanisme'))
        t = "Certificat d'urbanisme";

      if (t != '') t += ' > '; //else //console.log(key);
      //if(t=="") console.log(key);

      return t;
    };

    /***************************************************************************
      Gestion des établissements 
    ****************************************************************************/
    /**
     * Function: gethistoEtablissementDossier
     *
     * */
    function gethistoEtablissementDossier(idDossier) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.gethistoEtablissementDossier(int, idDossier);
        return defer.promise;
      } else {
        return $http.post(
          '/services/{portalid}/bacapp/{appname}/gethistoEtablissementDossier?f=json' +
            '&idDossier=' +
            idDossier
        );
      }
    }

    /**
     * Function: getEtablissementbyIdDossier
     */
    function getEtablissementbyIdDossier(appname, idDossier) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.getEtablissementbyIdDossier(int, idDossier);
        return defer.promise;
      } else {
        return $http.get(
          '/services/{portalid}/bacapp/{appname}/getEtablissementbyIdDossier?f=json' +
            '&appname=' +
            appname +
            '&idDossier=' +
            idDossier
        );
      }
    }

    /**
     * Function: getEtablissementbyId
     */
    function getEtablissementbyId(appname, etablissementId) {
      var promise = $http.get(
        '/services/{portalid}/bacapp/{appname}/getEtablissementbyId?f=json' +
          '&appname=' +
          appname +
          '&etablissementId=' +
          etablissementId
      );

      return promise;
    }

    /**
     * Function: addOrUpdateEtablissement
     */
    function addOrUpdateEtablissement(
      senddata,
      etablissementId,
      refDossier,
      appName
    ) {
      // If we're on the mobile application
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        var sdata = JSON.stringify(senddata);
        ancAppAndroid.addOrUpdateEtablissement(
          int,
          sdata,
          etablissementId,
          refDossier
        );
        return defer.promise;
      } else {
        // If we are in the web version
        appName = appName || appCfg.appname;
        var promise = $http.post(
          '/services/{portalid}/bacapp/' +
            appName +
            '/addOrUpdateEtablissement?f=json' +
            '&etablissementId=' +
            etablissementId +
            '&ref_dossier=' +
            refDossier,
          senddata
        );
        return promise;
      }
    }

    /**
     * removeEtablissement
     *
     *
     * @param {*} appName
     * @param {*} etablissementId
     */
    function removeEtablissement(appName, etablissementId) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.removeEtablissement(int, etablissementId);
        return defer.promise;
      } else {
        return $http.post(
          '/services/{portalid}/bacapp/' +
            appName +
            '/removeEtablissement?f=json' +
            '&appname=' +
            appName +
            '&etablissementId=' +
            etablissementId
        );
      }
    }

    /**
     * Function: removeEtablissementfromdossier
     */
    function removeEtablissementfromdossier(
      etablissementId,
      refDossier,
      appName
    ) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.removeEtablissementfromdossier(
          int,
          etablissementId,
          refDossier
        );
        return defer.promise;
      } else {
        appName = appName || appCfg.appname;
        return $http.post(
          '/services/{portalid}/bacapp/' +
            appName +
            '/removeEtablissementfromdossier?f=json' +
            '&etablissementId=' +
            etablissementId +
            '&ref_dossier=' +
            refDossier
        );
      }
    }

    /**
     * Function: choisirEtablissementForDossier
     */
    function choisirEtablissementForDossier(
      etablissementId,
      refDossier,
      appName
    ) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.choisirEtablissementForDossier(
          int,
          etablissementId,
          refDossier
        );
        return defer.promise;
      } else {
        appName = appName || appCfg.appname;
        return $http.post(
          '/services/{portalid}/bacapp/' +
            appName +
            '/choisirEtablissementForDossier?f=json' +
            '&etablissementId=' +
            etablissementId +
            '&ref_dossier=' +
            refDossier
        );
      }
    }

    /***************************************************************************
      Gestion des ActivitePrincipale et des  ActiviteSecondaire des établissements
    ****************************************************************************/
    /**
     * saveActivitePrincipaleOrSecondaire
     *
     *
     * @param {*} appName
     * @param {*} etablissementId
     * @param {*} typeActivte
     * @param {*} senddata
     */
    function saveActivitePrincipaleOrSecondaire(
      appName,
      etablissementId,
      typeActivte,
      senddata
    ) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        var sdata = JSON.stringify(senddata);
        ancAppAndroid.saveActivitePrincipaleOrSecondaire(
          int,
          sdata,
          etablissementId,
          typeActivte
        );
        return defer.promise;
      } else {
        return $http.post(
          '/services/{portalid}/bacapp/{appname}/saveActivitePrincipaleOrSecondaire?f=json' +
            '&appname=' +
            appName +
            '&etablissementId=' +
            etablissementId +
            '&typeActivte=' +
            typeActivte,
          senddata
        );
      }
    }

    /**
     * deleteActivitePrincipaleOrSecondaire
     *
     *
     * @param {*} appName
     * @param {*} etablissementId
     * @param {*} typeActivte
     */
    function deleteActivitePrincipaleOrSecondaire(
      appName,
      etablissementId,
      typeActivite
    ) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.deleteActivitePrincipaleOrSecondaire(
          int,
          etablissementId,
          typeActivite
        );
        return defer.promise;
      } else {
        return $http.post(
          '/services/{portalid}/bacapp/{appname}/deleteActivitePrincipaleOrSecondaire?f=json' +
            '&appname=' +
            appName +
            '&etablissementId=' +
            etablissementId +
            '&typeActivte=' +
            typeActivite
        );
      }
    }

    /**
     * getActivitePrincipaleOrActiviteSecondairesByIdEtablissement
     *
     * @param {*} appname
     * @param {*} idDossier
     */

    function getActivitePrincipaleOrActiviteSecondaires(
      appname,
      etablissementId,
      typeActivte
    ) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.getActivitePrincipaleOrActiviteSecondaires(
          int,
          etablissementId,
          typeActivte
        );
        return defer.promise;
      } else {
        return $http.post(
          '/services/{portalid}/bacapp/{appname}/getActivitePrincipaleOrActiviteSecondaires?f=json' +
            '&appname=' +
            appname +
            '&etablissementId=' +
            etablissementId +
            '&typeActivte=' +
            typeActivte
        );
      }
    }

    /***************************************************************************
      Gestion des classements Icpe 
    ****************************************************************************/
    /**
     * saveClassementIcpe
     *
     *
     * @param {*} appName
     * @param {*} etablissementId
     * @param {*} typeActivte
     * @param {*} senddata
     */
    function saveClassementIcpe(appName, etablissementId, senddata) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        var sdata = JSON.stringify(senddata);
        ancAppAndroid.saveClassementIcpe(int, etablissementId, sdata);
        return defer.promise;
      } else {
        return $http.post(
          '/services/{portalid}/bacapp/{appname}/saveClassementIcpe?f=json' +
            '&appname=' +
            appName +
            '&etablissementId=' +
            etablissementId,
          senddata
        );
      }
    }
    /**
     * getClassementIcpe
     *
     * @param {*} appname
     * @param {*} idDossier
     */

    function getClassementIcpe(appname, etablissementId) {
      if (typeof ancAppAndroid !== 'undefined') {
        var defer = $q.defer();
        var int = createDefer(defer);
        ancAppAndroid.getClassementIcpe(int, etablissementId);
        return defer.promise;
      } else {
        return $http.post(
          '/services/{portalid}/bacapp/{appname}/getClassementIcpe?f=json' +
            '&appname=' +
            appname +
            '&etablissementId=' +
            etablissementId
        );
      }
    }

    const addNewCommuneToData = (data, newCommune) => {
      data.extra.infosSassListeVillesCfg.push(newCommune);
      return data;
    };

    /***************************************************************************
      Gestion des listes Déroulantes et des domaines de restrictions 
    ****************************************************************************/
    /**
     * Function: checkrestrictiononcomponent
     */
    function checkrestrictiononcomponent(componentName, attributeName) {
      return $http.get(
        '/services/{portalid}/bacapp/{appname}/checkRestrictionOnComponent?f=json' +
          '&componentName=' +
          componentName +
          '&attributeName=' +
          attributeName
      );
    }

    /**
     * Function: updaterestrictionvalueoncomponent
     */
    function updaterestrictionvalueoncomponent(
      componentName,
      attributeName,
      valueId,
      newId
    ) {
      return $http.get(
        '/services/{portalid}/bacapp/{appname}/updateRestrictionValueOnComponent?f=json' +
          '&componentName=' +
          componentName +
          '&attributeName=' +
          attributeName +
          '&valueId=' +
          valueId +
          '&newId=' +
          newId
      );
    }

    /**
     * Function: getActifsControles
     */
    function getActifsControles(ids) {
      return $http.get(
        '/services/{portalid}/bacapp/' +
          appCfg.appname +
          '/getActifsControles?f=json' +
          '&ids=' +
          ids
      );
    }

    function prefillDcControleWithDossier(dossier, controle) {
      return $q.resolve(controle)
        .then(controleData => fillEtablissementActiviteData(dossier, controleData))
        .then(controleData => fillEtablissementData(dossier, controleData))
        .then(controleData => fillAdresseDossier(dossier, controleData, 'etablissement'))
        .then(controleData => fillAdresseDossier(dossier, controleData))
        .then(controleData => preFillReferent(dossier, controleData))
        .then(controleData => preFillPersonne(dossier, controleData, 'proprietaires'))
        .then(controleData => preFillPersonne(dossier, controleData, 'locataires'))
    }

    function fillEtablissementActiviteData (dossier, controle) {
      if (dossier.properties.activite_principale !== undefined) {
        controle.activite_principale = dossier.properties.activite_principale;
      }
      if (dossier.properties.activite_secondaire !== undefined) {
        controle.activite_secondaire = dossier.properties.activite_secondaire;
      }
      if (dossier.properties.details_icpe !== undefined) {
        controle.details_icpe = dossier.properties.details_icpe;
      }
      return controle;
    }

    function fillEtablissementData (dossier, controle) {
      if (!controle.info_generales) {
        controle.info_generales = {};
      }
      if (dossier.properties.etablissement) {
        if (dossier.properties.etablissement.nom) {
          controle.info_generales.nom_etablissement =
            dossier.properties.etablissement.nom;
        }
        if (dossier.properties.etablissement.siret) {
          controle.info_generales.siret_etablissement =
            dossier.properties.etablissement.siret;
        }
      }
      return controle;
    }

    function fillAdresseDossier (dossier, controle, destRes) {
      const dest = destRes || 'dossier';

      if (!controle.info_generales[dest]) {
        controle.info_generales[dest] = {};
      }

      if (!controle.caracteristiques_hab) {
        controle.caracteristiques_hab = {};
      }

      controle.info_generales[dest] = [
        'adresse_num_rue',
        'adresse_num_rue_extra',
        'adresse_rue',
        'adresse_cp',
        'adresse_ville',
        'num_tel',
        'email',
        'adresse_complement',
        'adresse_bp',
        'adresse_pays',
        'adresse_batiment',
        'adresse_appt',
        'adresse_etage',
        'adresse_escalier',
        'coordinates_x',
        'coordinates_y',
      ].filter(property => dossier.properties[property]).reduce((obj, property) => {
        obj[property] = angular.copy(dossier.properties[property]);
        return obj;
      }, {});

      return controle;
    }

    function preFillReferent (dossier, controle) {
      if (dossier && dossier.id) {
        return getEtablissementbyIdDossier(
          'BAC',
          dossier.id
        ).then((res)=> {
          if (
            gaJsUtils.checkNestedProperty('data.features.0.properties', res)
          ) {
            controle.info_generales.referent =
              res.data.features[0].properties;
          }
          return controle;
        }
        ).catch(() => controle);
      }
      return controle;
    }

    function preFillPersonne(dossier, controle, type_personne) {
      let type = type_personne;

      if (type_personne !== 'demandeur') {
        if (dossier.properties[type_personne].length) {
          return getInfosPersonne(
            dossier,
            controle,
            dossier.properties[type_personne][0].id,
            type
          );
        }
      }
      return controle;
    }

    function getInfosPersonne(dossier, controle, id_personne,  type_personne) {
      let type = 'proprietaire';
      if (type_personne === 'locataires') {
        type = 'locataire';
      } else {
        if (type_personne.indexOf('pers_present_ctrl') == 0) {
          type = 'pers_present_ctrl';
        }
      }

      if (
        !gaJsUtils.checkNestedProperty(
          'info_generales.' + type,
          controle
        )
      ){
        gaJsUtils.setNestedProperty('info_generales.' + type,
          controle,
          {}
        );
      }

      if (
        gaJsUtils.checkNestedProperty(
          'info_generales.' + type + '.type',
          controle
        )
      ){
        delete controle.info_generales[type]['type'];
      }

      return getpersonne(id_personne).then((res)=> {
        var pers = res.data.features[0];

        for (let k in pers.properties) {
          if (k === 'nom_complement') {
            controle.info_generales.proprietaire.nom_conjoint =
              pers.properties[k];
          } else {
            controle.info_generales[type][k] = pers.properties[k];
          }
        }

        // recup aussi equivalent redevance et type proprietaire
        if (
          type == 'proprietaire' ||
          type_personne == 'pers_present_ctrl_prop'
        ) {
          var proprietaireFti = FeatureTypeFactory.getFeatureByNameAndDatastore(
            appCfg.main.datastore,
            'kis_bac_dossier_proprietaire'
          );

          return QueryFactory.data(
            proprietaireFti.uid,
            "ref_dossier = '" +
              dossier.id +
              "' " +
              "AND id_personne = '" +
              pers.id +
              "' " +
              "AND courant='true'"
          ).then((res)=> {
            if (res.data.features.length) {
              const p = res.data.features[0].properties;
              controle.info_generales[type][
                'est_redevable'
              ] = p.est_redevable ? '1' : false;

              if (type === 'pers_present_ctrl'){
                controle.info_generales[type]['type'] = getValueType(
                  'proprietaire',
                  p.type_proprietaire
                );
              } else {
                controle.info_generales[type]['type_proprietaire'] =
                  '' + p.type_proprietaire;
              }

              if (
                gaJsUtils.checkNestedProperty(
                  'datesDossier.debut_proprietaire',
                  controle
                )
              ){
                controle.datesDossier.debut_proprietaire = '' + p.debut;
              }
              if (
                gaJsUtils.checkNestedProperty(
                  'datesDossier.fin_proprietaire',
                  controle
                )
              ){
                controle.datesDossier.fin_proprietaire = '' + p.fin;
              }
            }
            return controle;
          });
        }
        return controle;
      });
    }

    function getValueType (type, value) {
      let fti;
      let indexAttr;
      let res;

      if (type === 'demandeur') {
        fti = scope.demandeurFti;
      }

      if (type === 'proprietaire') {
        fti = scope.proprietaireFti;
      }

      fti.attributes.forEach((attr, i)=> {
        if (attr.name.indexOf('type') == 0){
          indexAttr = i;
        }
      });

      res = fti.attributes[indexAttr].restrictions[0].listofValues[value]
        ? fti.attributes[indexAttr].restrictions[0].listofValues[value]
        : null;

      return res;
    }

    function isDcControle(controlType) {
      return (appCfg.main.controleCfg.find(control => control.type === controlType) || {})
        .template === 'DC.html';
    }

     /**
     * Get infos locataires or proprietaire
     */
      const getInfosLocataireOrProprio = (idDossier, idPersonne, typePersonne) => {
        return $http.get(
          '/services/{portalid}/bacapp/' +
            appCfg.appname +
              '/getInfosLocataireOrProprio?f=json&idDossier=' + idDossier + '&typePersonne=' + typePersonne + '&idPersonne=' + idPersonne
        ); 
      }

    return {
      BacAppFactory: BacAppFactory,
      getdossiers: getdossiers,
      sendResultBackDossiers: sendResultBackDossiers,
      getdossier: getdossier,
      getdossier_villes: getdossier_villes,
      initdatabase: initdatabase,
      checkbacappdata: checkbacappdata,
      adddossier: adddossier,
      checkdossiersamereference: checkdossiersamereference,
      updatedossier: updatedossier,
      getpersonnes: getpersonnes,
      getpersonne: getpersonne,
      addpersonne: addpersonne,
      updatepersonne: updatepersonne,
      getparcelles: getparcelles,
      getparcelle: getparcelle,
      checkparcellealreadyused: checkparcellealreadyused,
      addpersonnetodossier: addpersonnetodossier,
      removepersonneencoursfromdossier: removepersonneencoursfromdossier,
      getancpersonne: getancpersonne,
      gethistopersonnesdossier: gethistopersonnesdossier,
      addparcelletodossier: addparcelletodossier,
      removeparcellefromdossier: removeparcellefromdossier,
      updatestatutdossiers: updatestatutdossiers,
      getdossierbycontroleid: getdossierbycontroleid,
      getcontroledetailexterne: getcontroledetailexterne,
      changeControleExterneDetail: changeControleExterneDetail,
      activecontroledetailexterne: activecontroledetailexterne,
      bacDossierToDossier: bacDossierToDossier,

      /* controles */
      getcontroles: getcontroles,
      removecontrole: removecontrole,
      addcontrole: addcontrole,
      updatecontrole: updatecontrole,
      addcontroledetail: addcontroledetail,
      getcontroledetail: getcontroledetail,
      getCtrlFormCfg: getCtrlFormCfg,
      getAllCtrlFormCfg: getAllCtrlFormCfg,
      getNewControleData: getNewControleData,
      /* factures */
      generatefacturesdolibarr: generatefacturesdolibarr,
      getmontantfactures: getmontantfactures,
      changestatutfactures: changestatutfactures,
      imprimerfactures: imprimerfactures,
      /* docs */
      uploaddashboarddoc: uploaddashboarddoc,
      removedashboarddoc: removedashboarddoc,
      listdashboarddocs: listdashboarddocs,
      downloaddashboarddoc: downloaddashboarddoc,
      generatereport: generatereport,
      getreportpdf: getreportpdf,
      /* cfg */
      appCfg: appCfg,
      getAppCfg: getAppCfg,
      updateAppCfg: updateAppCfg,
      /* misc */
      getControleName: getControleName,
      getNumeroAuto: getNumeroAuto,
      base64topng: base64topng,
      getZipDocumentsTypes: getZipDocumentsTypes,
      updatepersonhistory: updatepersonhistory,
      /** extract html **/
      extractModelFromForm: extractModelFromForm,
      getngincludeduhtml: getngincludeduhtml,
      htmlformtojson: htmlformtojson,
      create_controle_json_mapping_file: create_controle_json_mapping_file,
      getControlesHTML: getControlesHTML,
      getextractedjsondata: getextractedjsondata,
      getextractedjsondataurl: getextractedjsondataurl,
      /** reglementaire **/
      refreshnationalreglementaire: refreshnationalreglementaire,
      getreglementaire: getreglementaire,
      addreglementaire: addreglementaire,
      removereglementaire: removereglementaire,
      /** recherche **/
      setindexation: setindexation,
      indexcontroles: indexcontroles,
      getfacturespdf: getfacturespdf,
      /* mobile */
      addtournee: addtournee,
      gettournee: gettournee,
      getMobileTournee: getMobileTournee,
      getMobileTourneeProgression: getMobileTourneeProgression,
      gettournees: gettournees,
      getAllTournees: getAllTournees,
      synchrotournee: synchrotournee,
      synchroTourneeProgression: synchroTourneeProgression,
      removetournee: removetournee,
      debloquetournee: debloquetournee,
      debloqueDossier: debloqueDossier,
      initappCfg: initappCfg,
      buildFakeCtrlReponseFtiForElasticSearch: buildFakeCtrlReponseFtiForElasticSearch,
      getBuildedFakeCtrlReponseFtiForElasticSearch: getBuildedFakeCtrlReponseFtiForElasticSearch,
      dataResultAndroid: dataResultAndroid,
      getDossiersTournee: getDossiersTournee,
      /* divers */
      getActifsControles: getActifsControles,
      /* specifique BAC */

      /* demandes d'urbanisme */
      addobjetbranchementtodossier: addobjetbranchementtodossier,
      adddemandeurbanisme: adddemandeurbanisme,
      removedemandeurbanisme: removedemandeurbanisme,
      updatedemandeurbanisme: updatedemandeurbanisme,
      getdemandeurbanisme: getdemandeurbanisme,

      /* caracteristiques construction */
      getcaracteristiqueconstruction: getcaracteristiqueconstruction,
      addcaracteristiqueconstruction: addcaracteristiqueconstruction,

      getListeDossiersCfg: getListeDossiersCfg,
      getChoixStatutRDV: getChoixStatutRDV,

      /* Données des etablissements */
      gethistoEtablissementDossier: gethistoEtablissementDossier,
      getEtablissementbyIdDossier: getEtablissementbyIdDossier,
      getEtablissementbyId: getEtablissementbyId,
      addOrUpdateEtablissement: addOrUpdateEtablissement,
      removeEtablissementfromdossier: removeEtablissementfromdossier,
      removeEtablissement: removeEtablissement,
      choisirEtablissementForDossier: choisirEtablissementForDossier,

      /* Données des activtés des etablilssements */
      deleteActivitePrincipaleOrSecondaire: deleteActivitePrincipaleOrSecondaire,
      saveActivitePrincipaleOrSecondaire: saveActivitePrincipaleOrSecondaire,
      getActivitePrincipaleOrActiviteSecondaires: getActivitePrincipaleOrActiviteSecondaires,

      /* Données des classements Icpe */
      saveClassementIcpe: saveClassementIcpe,
      getClassementIcpe: getClassementIcpe,
      addNewCommuneToData: addNewCommuneToData,
      getAlerteColorClass: getAlerteColorClass,

      /* Gestion des LDéroulantes et des DRestrictions */
      checkrestrictiononcomponent: checkrestrictiononcomponent,
      updaterestrictionvalueoncomponent: updaterestrictionvalueoncomponent,
      getIdLastPersonneAdded:getIdLastPersonneAdded,
      getInfosLocataireOrProprio:getInfosLocataireOrProprio
    };
  };
  BacAppFactory.$inject = [
    '$http',
    '$location',
    'ConfigFactory',
    '$q',
    'FeatureTypeFactory',
    'gaUrlUtils',
    '$rootScope',
    '$filter',
    'gaDomUtils',
    'gaJsUtils',
    '$sce',
    'UsersFactory',
    'QueryFactory',
    "CommonFactory",
    "PortalsFactory"
  ];
  return BacAppFactory;
});
