'use strict';
define(function() {
  var SirocoFactory = function(
    $http,
    $q,
    $timeout,
    gaDomUtils,
    ConfigFactory,
    $location,
    ApplicationFactory,
    FeatureAttachmentFactory,
    ReportFactory,
    ParametersFactory,
    FeatureTypeFactory,
    QueryFactory
  ) {
    var SirocoFactory = {}; /** * Class : SirocoFactory * Factory WebServices **/ /** * Function: handleexport **/

    function checkExportData(appname, methode, fileindex) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/checkExportData?f=json' +
          '&appname=' +
          appname
      );
      promise.then(function(res) {});
      return promise;
    }
    function handleexport(appname, methode, fileindex, fieldsToExport) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/export?f=json' +
          '&appname=' +
          appname +
          '&methode=' +
          methode +
          '&fileindex=' +
          fileindex +
          '&fields=' +
          fieldsToExport
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: handleimport **/
    function handleimport(appname, filename, methode) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/import?f=json' +
          '&appname=' +
          appname +
          '&filename=' +
          filename +
          '&methode=' +
          methode
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: getemptych **/
    function getemptych(appname) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/getEmptyCh?f=json' +
          '&appname=' +
          appname
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: getdomaines **/
    function getdomaines(appname) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/getDomaines?f=json' +
          '&appname=' +
          appname
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: generationgraphe **/
    function generationgraphe(
      appname,
      methode,
      seuil,
      seuils,
      typeSeuils,
      nomVariantes,
      nomVariante
    ) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/GenerationGraphe?f=json' +
          '&appname=' +
          appname +
          '&methode=' +
          methode +
          '&seuil=' +
          seuil +
          '&seuils=' +
          seuils +
          '&typeSeuils=' +
          typeSeuils +
          '&nomVariantes=' +
          nomVariantes +
          '&nomVariante=' +
          nomVariante
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: choixvariante **/
    function choixvariante(methode, appname, nomVariante, threadId, seuils) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/ChoixVariante?f=json' +
          '&methode=' +
          methode +
          '&appname=' +
          appname +
          '&nomVariante=' +
          nomVariante +
          '&threadId=' +
          threadId +
          '&seuils=' +
          seuils
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: calculerchantier **/
    function calculerchantier(appname, idChantier) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/CalculerChantier?f=json' +
          '&appname=' +
          appname +
          '&idChantier=' +
          idChantier
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: creertranches **/
    function creertranches(methode, appname, anneeDebut, nbAnnees, valeur) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/CreerTranches?f=json' +
          '&methode=' +
          methode +
          '&appname=' +
          appname +
          '&anneeDebut=' +
          anneeDebut +
          '&nbAnnees=' +
          nbAnnees +
          '&valeur=' +
          valeur
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: listertranches **/
    function listertranches(appname) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/ListerTranches?f=json' +
          '&appname=' +
          appname
      );
      promise.then(function(res) {});
      return promise;
    }

    /** * Function: modifiertranche **/
    function modifiertranche(annee, valeur) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/ModifierTranche?f=json' +
          '&annee=' +
          annee +
          '&valeur=' +
          valeur
      );
      promise.then(function(res) {});
      return promise;
    }

    /** * Function: handleremovecasse **/
    function handleremovecasse(filename, appname) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/removeCasse?f=json' +
          '&filename=' +
          filename +
          '&appname=' +
          appname
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: parametresfrombddmetier **/
    function parametresfrombddmetier(appname) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/parametresFromBddMetier?f=json' +
          '&appname=' +
          appname
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: generationvariante **/
    function generationvariante(appname, methode, nomVariante, threadId) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/GenerationVariante?f=json' +
          '&appname=' +
          appname +
          '&methode=' +
          methode +
          '&nomVariante=' +
          nomVariante +
          '&threadId=' +
          threadId
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: supprimervariante **/
    function supprimervariante(
      appname,
      methode,
      nomVariante,
      threadId,
      seuils,
      typeSeuils,
      nomVariantes
    ) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/SupprimerVariante?f=json' +
          '&appname=' +
          appname +
          '&methode=' +
          methode +
          '&nomVariante=' +
          nomVariante +
          '&threadId=' +
          threadId +
          '&seuils=' +
          seuils +
          '&typeSeuils=' +
          typeSeuils +
          '&nomVariantes=' +
          nomVariantes
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: actualiserchantiers **/
    function actualiserchantiers(methode, threadId) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/ActualiserChantiers?f=json' +
          '&methode=' +
          methode +
          '&threadId=' +
          threadId
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: tableauprogrammation **/
    function tableauprogrammation(methode) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/TableauProgrammation?f=json' +
          '&methode=' +
          methode
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: calculimportancecanas **/
    function calculimportancecanas(methode, nomVariante, appname, threadId) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/CalculImportanceCanas?f=json' +
          '&methode=' +
          methode +
          '&nomVariante=' +
          nomVariante +
          '&appname=' +
          appname +
          '&threadId=' +
          threadId
      );
      promise.then(function(res) {});
      return promise;
    } /** * Function: initializedatabase **/
    function initializedatabase(datastore) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/initializeDataBase?f=json&datastore=' +
          datastore
      );
      promise.then(function(res) {});
      return promise;
    }

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

      return promise;
    }

    function upgradeDataModel(appname) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/upgradeDataModel?f=json' +
          '&appname=' +
          appname
      );

      return promise;
    }

    /**
     * check thread progression
     * @param threadid
     * @param service
     * @param varianteName
     */
    function displayGenerationProgressionThread(
      threadId,
      service,
      varianteName
    ) {
      var baseUrl =
        '/services/{portalid}/siroco/{appname}/' +
        service +
        '?methode=GetProgression' +
        '&nomVariante=' +
        varianteName +
        '&threadId=' +
        threadId;

      var promise = $http.get(baseUrl);

      promise.then(function(res) {
        if (res.data.strValeur !== '') {
          gaDomUtils.setGlobalLoaderScaleValue(res.data.strValeur);
        }
      });
    }

    /**
     * check if thread is running
     * @param threadId
     * @param varianteName
     * @param service
     * @param methode
     * @param checkPromise
     * @returns {*}
     */
    function checkGeneration(
      threadId,
      varianteName,
      service,
      methode,
      checkPromise
    ) {
      if (!checkPromise) {
        var checkPromise = $q.defer();
      }

      var baseUrl =
        '/services/{portalid}/siroco/{appname}/' +
        service +
        '?methode=' +
        methode +
        '&nomVariante=' +
        varianteName +
        '&threadId=' +
        threadId;

      var promise = $http.get(baseUrl);
      promise.then(
        function(res) {
          if (res.data.strValeur == 'running') {
            $timeout(function() {
              checkGeneration(
                threadId,
                varianteName,
                service,
                methode,
                checkPromise
              );
              displayGenerationProgressionThread(
                threadId,
                service,
                varianteName
              );
            }, 500);
          } else {
            checkPromise.resolve(res);
          }
        },
        function() {
          // error
          checkPromise.reject(res);
        }
      );
      return checkPromise.promise;
    }

    /**
     * getSirocoCfg
     * @returns {HttpPromise}
     */
    var sirocoCfg;
    function getSirocoCfg() {
      var sirocoCfgPromise = $q.defer();

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

      // retrieve appname
      sirocoCfg = {
        appname: $location.search().app,
        layersNames: {},
      };

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

        if (sirocoCfg.mainConfig == '') {
          $location.path('/siroco/nocfg');
          sirocoCfgPromise.reject();
          return sirocoCfgPromise.promise;
        }

        // setLayerNames
        var toRetrieve = [
          'cana_aep',
          'cana_aep_import',
          'fuite',
          'noeud_import',
          'noeud_1',
          'chantier',
        ];
        // console.log( sirocoCfg);

        if (sirocoCfg.mainConfig.featureSources != undefined)
          sirocoCfg.mainConfig.featureSources.forEach(function(ft) {
            var found = toRetrieve.indexOf(ft.featureSourceId);
            if (found != -1) {
              sirocoCfg.layersNames[toRetrieve[found]] = ft.featureSourceName;
            }
          });

        // retrieve the app uid
        ApplicationFactory.get().then(function() {
          ApplicationFactory.resources.applications.forEach(function(app) {
            if (app.name == sirocoCfg.appname) {
              sirocoCfg.appuid = app.uid;
            }
          });
          var jsonCfg = JSON.stringify(sirocoCfg);
          sessionStorage.setItem('sirocoCfg', jsonCfg);
          sirocoCfgPromise.resolve(jsonCfg);
        });
      });
      return sirocoCfgPromise.promise;
    }

    /**
     * get Casse or Criticite file
     * @param type
     * @returns {*}
     */
    var getCasseCriticite = function(type) {
      return FeatureAttachmentFactory.list('siroco', type);
    };

    /**
     * Function: getstructuredonnesdescriptives
     */
    function getstructuredonnesdescriptives(appname, ftType) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/getStructureDonnesDescriptives?f=json' +
          '&appname=' +
          appname +
          '&fttype=' +
          ftType
      );

      return promise;
    }

    /**
     * Function: getsirocomissinginfo
     * parameters:
     *    appname: nom de l'application
     *    ftType: type du feature type ("aep_cana_import","aep_fuite")
     */
    function getsirocomissinginfo(appname, ftType) {
      var promise = $http.get(
        '/services/{portalid}/siroco/{appname}/getSirocoMissingInfo?f=json&appname=' +
          appname +
          '&fttype=' +
          ftType
      );

      return promise;
    }

    /**
     *     Calcul la boundic box de l'objet passé en paramètre,
     * avec une marger autour de celui-ci.
     *
     * @param {Object} feature
     */
    function getBbFromFeature(feature) {
      var bb = {},
        ii,
        jj,
        kk,
        coord;

      //-- Récupérer la BB du chantier
      var geom = feature.geometry.coordinates;
      bb.xmin = bb.xmax = geom[0][0][0][0];
      bb.ymin = bb.ymax = geom[0][0][0][1];
      for (ii = 0; ii < geom.length; ii++) {
        for (jj = 0; jj < geom[ii].length; jj++) {
          for (kk = 0; kk < geom[ii][jj].length; kk++) {
            coord = geom[ii][jj][kk];
            if (coord[0] < bb.xmin) bb.xmin = coord[0];
            if (coord[0] > bb.xmax) bb.xmax = coord[0];
            if (coord[1] < bb.ymin) bb.ymin = coord[1];
            if (coord[1] > bb.ymax) bb.ymax = coord[1];
          }
        }
      }
      var delta = (bb.xmax - bb.xmin) / 2;
      bb.xmax += delta;
      bb.ymax += delta;
      bb.xmin -= delta;
      bb.ymin -= delta;

      return bb;
    }

    function getBbForPrev(
      tagPixWidth,
      tagPixHeight,
      areaPixWidth,
      areaPixHeight,
      groundBB,
      cx,
      cy
    ) {
      var ww, hh, bb, wwall, hhall;

      ww = groundBB.xmax - groundBB.xmin;
      hh = groundBB.ymax - groundBB.ymin;
      if (ww > hh) {
        wwall = (areaPixWidth * ww) / tagPixWidth / 2;
        hhall = (areaPixHeight * ww) / tagPixWidth / 2;
      } else {
        wwall = (areaPixWidth * hh) / tagPixHeight / 2;
        hhall = (areaPixHeight * hh) / tagPixHeight / 2;
      }
      return {
        xmin: cx - wwall,
        xmax: cx + wwall,
        ymin: cy - hhall,
        ymax: cy + hhall,
      };
    }

    /**
     *    Construction de l'URL permettant d'ateindre le serveur WMS qui retourne la carte.
     *
     * @param {Object} chantier
     */
    function getWmsMapUrl1(chantier, canaBb) {
      var ii,
        url0,
        url,
        urlRet = {},
        portal;
      var bb = {},
        bbprev01;
      var newHh, newWw;

      var cw, ch;
      cw = canaBb[2] - canaBb[0];
      ch = canaBb[3] - canaBb[1];

      //-- CARTE KIS
      bb = getBbFromFeature(chantier);
      //-- Construire l'url'
      ii = location.hash.indexOf('portal=');
      portal = location.hash.substr(ii + 7);
      ii = portal.indexOf('&');
      portal = portal.substr(0, ii);
      url0 = location.origin + '/services/' + portal + '/geoserver';
      url0 += '/wms?token=' + localStorage.auth_token;
      var fac = 440 / 363;
      var hh = bb.ymax - bb.ymin;
      var ww = bb.xmax - bb.xmin;
      var centerx = (bb.xmin + bb.xmax) / 2;
      var centery = (bb.ymin + bb.ymax) / 2;
      if (hh > ww) {
        newWw = (hh * fac) / 2.0;
        bb.xmin = centerx - newWw;
        bb.xmax = centerx + newWw;
      } else {
        newHh = ww / fac / 2.0;
        bb.ymin = centery - newHh;
        bb.ymax = centery + newHh;
      }
      canaBb[0] = centerx - cw - cw / 2;
      canaBb[2] = centerx + cw + cw / 2;
      canaBb[1] = centery - ch - ch / 2;
      canaBb[3] = centery + ch + ch / 2;

      url0 += '&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image%2Fpng';
      url0 +=
        '&TRANSPARENT=true&LAYERS=siroco_chantier%2Caep_cana%2CAEP_ANOMALIE';
      url0 += '&tiled=false&STYLES=chantier1%2CAEP_CANA_IMPORTANCE%2Canomalie';
      url0 += '&OPACITY=1%2C1%2C1&CQL_FILTER=1%3D1;1%3D1;1%3D1';
      url = url0 + '&type=g2c&t=245&WIDTH=880&HEIGHT=726&CRS=EPSG%3A3857';
      url +=
        '&BBOX=' +
        bb.xmin +
        '%2C' +
        bb.ymin +
        '%2C' +
        bb.xmax +
        '%2C' +
        bb.ymax;
      urlRet.plan = url;

      //-- Plan pour prévisualisation zoom proche
      url = url0 + '&type=g2c&t=245&WIDTH=600&HEIGHT=600&CRS=EPSG%3A3857';
      bbprev01 = getBbForPrev(110, 110, 600, 600, bb, centerx, centery);
      //url = url0 + "&BBOX="+(bb.xmin-ww)+"%2C"+(bb.ymin-hh)+"%2C"+(bb.xmax+ww)+"%2C"+(bb.ymax+hh);
      url += '&BBOX=' + bbprev01.xmin + '%2C' + bbprev01.ymin + '%2C';
      url += bbprev01.xmax + '%2C' + bbprev01.ymax;
      urlRet.plan_prev01 = url;

      //-- Plan pour prévisualisation zoom emprise canalisation
      url = url0 + '&type=g2c&t=245&WIDTH=180&HEIGHT=180&CRS=EPSG%3A3857';
      url +=
        '&BBOX=' +
        canaBb[0] +
        '%2C' +
        canaBb[1] +
        '%2C' +
        canaBb[2] +
        '%2C' +
        canaBb[3];
      urlRet.plan_prev02 = url;

      //-- FOND DE PLAN
      //https://magosm.magellium.com/geoserver/ows?service=wms&version=1.3.0&request=GetCapabilities

      url0 = 'https://ows.terrestris.de/osm/service?';
      url0 += 'SERVICE=WMS&VERSION=1.1.0&REQUEST=GetMap&';
      url0 += 'FORMAT=image%2Fpng&TRANSPARENT=true&';
      url0 += 'layers=OSM-WMS&layers=OSM-Overlay-WMS&';
      url0 += 'styles=&styles=&styles=&styles=&';
      url = url0 + 'WIDTH=880&HEIGHT=726&SRS=EPSG%3A3857&';
      url +=
        'BBOX=' + bb.xmin + '%2C' + bb.ymin + '%2C' + bb.xmax + '%2C' + bb.ymax;
      urlRet.fdplan = url;

      //-- Fond de plan pour prévisualisation zoom proche
      url = url0 + 'WIDTH=600&HEIGHT=600&SRS=EPSG%3A3857&';
      //url = url0 + "BBOX="+(bb.xmin-ww)+"%2C"+(bb.ymin-hh)+"%2C"+(bb.xmax+ww)+"%2C"+(bb.ymax+hh);
      url += '&BBOX=' + bbprev01.xmin + '%2C' + bbprev01.ymin + '%2C';
      url += bbprev01.xmax + '%2C' + bbprev01.ymax;
      urlRet.fdplan_prev01 = url;

      //-- Fond de plan pour prévisualisation zoom emprise canalisation
      url = url0 + 'WIDTH=180&HEIGHT=180&SRS=EPSG%3A3857&';
      url +=
        '&BBOX=' +
        canaBb[0] +
        '%2C' +
        canaBb[1] +
        '%2C' +
        canaBb[2] +
        '%2C' +
        canaBb[3];
      urlRet.fdplan_prev02 = url;

      return urlRet;
    }

    /**
     *    Construction des URL pour la carte KIS et le fond de plan.
     * Ici, on se contente d'un aiguillage afin de fabriquer directement
     * les URLs si le chantier est fourni dans le bon système de projection,
     * ou afin d'attendre la relecture de la feature dans le bon système
     * de projection avant de fabriquer les URLs.
     *
     * @param {Object} chantier
     * @param {Object} crsOk
     */
    function getWmsMapUrl(chantier, crsOk) {
      var deferred = $q.defer();

      //-- Le chantier est-il dans le bon sustème de projection ?
      var descCana = FeatureTypeFactory.getFeatureByNameAndDatastore(
        sirocoCfg.mainConfig.datastore,
        sirocoCfg.layersNames.cana_aep
      );
      FeatureTypeFactory.getExtent(descCana.uid, 'EPSG:3857').then(function(
        res
      ) {
        var canaBb = res.data;
        if (crsOk === false) {
          //-- L'appelant dit que non: on relit le feature avec le bon système de projection.
          var desc = FeatureTypeFactory.getFeatureByNameAndDatastore(
            sirocoCfg.mainConfig.datastore,
            'siroco_chantier'
          );

          getSirocoCfg().then(function() {
            QueryFactory.get(
              desc.uid,
              chantier.id,
              'EPSG:3857'
            ).then(function(res) {
              var chantierFromDb = res.data.features[0];
              deferred.resolve(getWmsMapUrl1(chantierFromDb, canaBb));
            });
          });
        }
        //-- L'appelant dit que oui: on peut préparer l'url de la carte de suite.
        else deferred.resolve(getWmsMapUrl1(chantier, canaBb));
      });

      return deferred.promise;
    }

    function getRapportChantier(chantier, crsOk) {
      ParametersFactory.getbytype('siroco_variante_selectionnee').then(function(
        res
      ) {
        if (res.data.length != undefined && res.data.length != 0) {
          var variante = res.data[0].name;
          var reportParams = {};
          var url, portal, ii;

          getWmsMapUrl(chantier, crsOk).then(function(url) {
            reportParams['VARIANTE'] = variante;
            var ii = chantier.id.indexOf('.');
            reportParams['IDCHANTIER_fid'] = parseInt(
              chantier.id.substr(ii + 1)
            );
            reportParams['PLAN'] = url.plan;
            reportParams['FDPLAN'] = url.fdplan;
            reportParams['PLAN_PREV01'] = url.plan_prev01;
            reportParams['FDPLAN_PREV01'] = url.fdplan_prev01;
            reportParams['PLAN_PREV02'] = url.plan_prev02;
            reportParams['FDPLAN_PREV02'] = url.fdplan_prev02;
            ReportFactory.consultgeneratedreport(
              reportParams,
              false,
              'FicheChantier',
              sirocoCfg.mainConfig.datastore,
              'pdf'
            ).then(function(res) {
              if (res.data.strValeur != undefined)
                window.open('/' + res.data.strValeur);
              else window.open('/' + res.data);
            });
          });
        }
      });
    }

    return {
      SirocoFactory: SirocoFactory,
      //setfileresponsefromsirocoret: setfileresponsefromsirocoret,
      // getuser: getuser,
      checkExportData: checkExportData,
      handleexport: handleexport,
      handleimport: handleimport,
      getemptych: getemptych,
      getdomaines: getdomaines,
      //getretforerrmess: getretforerrmess,
      generationgraphe: generationgraphe,
      choixvariante: choixvariante,
      calculerchantier: calculerchantier,
      creertranches: creertranches,
      listertranches: listertranches,
      modifiertranche: modifiertranche,
      //getbaseurlfromreq: getbaseurlfromreq,
      handleremovecasse: handleremovecasse,
      parametresfrombddmetier: parametresfrombddmetier,
      generationvariante: generationvariante,
      supprimervariante: supprimervariante,
      actualiserchantiers: actualiserchantiers,
      tableauprogrammation: tableauprogrammation,
      calculimportancecanas: calculimportancecanas,
      initializedatabase: initializedatabase,
      datavalidation: datavalidation,
      // extra
      checkGeneration: checkGeneration,
      getSirocoCfg: getSirocoCfg,
      getCasseCriticite: getCasseCriticite,
      getstructuredonnesdescriptives: getstructuredonnesdescriptives,
      getsirocomissinginfo: getsirocomissinginfo,
      getRapportChantier: getRapportChantier,
      upgradeDataModel: upgradeDataModel,

      /**
       * HPO get siroco map creation
       * @type {Array}
       */
      getWmsMapUrl1: getWmsMapUrl1,
    };
  };
  SirocoFactory.$inject = [
    '$http',
    '$q',
    '$timeout',
    'gaDomUtils',
    'ConfigFactory',
    '$location',
    'ApplicationFactory',
    'FeatureAttachmentFactory',
    'ReportFactory',
    'ParametersFactory',
    'FeatureTypeFactory',
    'QueryFactory',
  ];
  return SirocoFactory;
});
