Ext.namespace('Atolcd', 'Atolcd.Right');
Ext.namespace('Atolcd', 'Atolcd.renderer');

// "correctif" pour afficher la valeur d'une combo, après le load du store
Ext.override(Ext.form.ComboBox, {
  setValue: function(v){
    // begin patch
    // Store not loaded yet? Set value when it *is* loaded.
    // Defer the setValue call until after the next load.
    if (this.store.getCount() == 0) {
      this.store.on('load', this.setValue.createDelegate(this, [v]), null, {
        single: true
      });
      return;
    }
    // end patch
    var text = v;
    if (this.valueField) {
      var r = this.findRecord(this.valueField, v);
      if (r) {
        text = r.data[this.displayField];
      } else if (this.valueNotFoundText !== undefined) {
        text = this.valueNotFoundText;
      }
    }
    this.lastSelectionText = text;
    if (this.hiddenField) {
      this.hiddenField.value = v;
    }
    Ext.form.ComboBox.superclass.setValue.call(this, text);
    this.value = v;
  }
});

/**
 * Correctif bug alignement checkbox sous I.E.
 * http://www.sencha.com/forum/showthread.php?44312-2.2-IE-and-FF-Checkbox-alignment-problems
 */
Ext.override(Ext.form.Checkbox, {
  getResizeEl : function(){
    if(!this.resizeEl){
        this.resizeEl = Ext.isSafari||Ext.isIE ? this.wrap : (this.wrap.up('.x-form-element', 5) || this.wrap);
    }
    return this.resizeEl;
    }
});

Ext.util.Format.frMoney = function(v){
  v = (Math.round((v - 0) * 100)) / 100;
  v = (v == Math.floor(v)) ? v + ".00" : ((v * 10 == Math.floor(v * 10)) ? v + "0" : v);
  v = String(v);
  var ps = v.split('.');
  var whole = ps[0];
  var sub = ps[1] ? '.' + ps[1] : '.00';
  var r = /(\d+)(\d{3})/;
  while (r.test(whole)) {
    whole = whole.replace(r, '$1' + ' ' + '$2');
  }
  v = whole + sub;
  if (v.charAt(0) == '-') {
    return '-' + v.substr(1) + ' €';
  }
  return v + " €";
}

Ext.util.Format.frMoneyUnitee = function(v){
  v = Math.round(v);
  v = String(v);
  return v + " €";
}
Ext.applyIf(Ext.ButtonToggleMgr, {
  getPressed: function(group){
    var g = groups[group];
    if (g) {
      for (var i = 0, len = g.length; i < len; i++) {
        if (g[i].pressed === true) {
          return g[i];
        }
      }
    }
    return null;
  }
});

Atolcd.setValueCombo = function(cbo, value){
  if (cbo != null && value != null) {
    var indexRecord = cbo.store.find(cbo.valueField, value);
    if (indexRecord < 0) indexRecord = 0;
    var record = cbo.store.getAt(indexRecord);
    if (typeof record != 'undefined') cbo.onSelect(record, indexRecord);
    return record;
  }
};

// Renderer à utiliser dans les grilles pour les types booléens
Atolcd.rendererBool = function(value, metadata, record, rowIndex, colIndex, store){
  if (value === true || value === 1 || value === 'true' || value === 't' || value === 'oui') {
    return '<div class="isok">&nbsp;</div>';
  }
  return '';
};

// Renderer à utiliser dans les grilles pour afficher une valeur à 2 chiffres
// après la virgule
Atolcd.rendererFloat2 = function(value, metadata, record, rowIndex, colIndex, store){
  value = parseFloat(value);
  if (!isNaN(value) && value != null) {
    return value.toFixed(2);
  }
  return '';
};


if (!Atolcd.ContextMgr) {

  Atolcd.ContextMgr = function(){
  
    var _cp = new Ext.state.CookieProvider({
      expires: new Date(new Date().getTime() + (1000 * 60 * 30)) // 30 minutes
    });
    // Ext.state.Manager.setProvider(_cp);
    
    var _listComponent = new Ext.util.MixedCollection();
    
    var _idpage = null;
    
    return {
      // Fonction appelé une fois qui définit l'identifiant de la page en cour
      setPage: function(idpage){
        _idpage = idpage;
      },
      
      // Fonction qui permet à un composant de s'enregistrer, et de recevoir
      // en retour
      // un objet de config si il existait dans la page en cour
      register: function(comp){
        if (comp != null && !_listComponent.containsKey(comp.id)) {
          _listComponent.add(comp.id, comp);
          var compContext = _cp.get("page-" + _idpage, comp.id);
          return compContext[comp.id] || {};
        }
      },
      
      // Fonction qui va appeler la fonction getContext de chaque élément:
      saveContext: function(){
        var tab = {};
        for (var i = 0; i < _listComponent.getCount(); i++) {
          var comp = _listComponent.itemAt(i);
          if (comp != null && comp.getContext) {
            tab[comp.id] = comp.getContext();
          }
        }
        _cp.set("page-" + _idpage, tab);
      },
      
      setPageObjectContext: function(idpage, id, newContext, clearOldContext){
        var contextActuel = (clearOldContext == true ? {} : _cp.get("page-" + idpage, id));
        if (contextActuel && contextActuel != id) {
          Ext.apply(contextActuel || {}, newContext || {});
        } else {
          contextActuel = newContext;
        }
        
        _cp.set("page-" + idpage, contextActuel);
        return contextActuel;
      },
      
      getPageObjectContext: function(idpage, id){
        var ctx = _cp.get("page-" + idpage, id) || {};
        return ctx;
      },
      
      setPageContext: function(idpage, newContext, clearOldContext){
        return this.setPageObjectContext(idpage, "CP-" + idpage, newContext, clearOldContext)
      },
      
      getPageContext: function(idpage){
        if (typeof idpage == 'undefined' || idpage == null) {
          idpage = _idpage;
        }
        return this.getPageObjectContext(idpage, "CP-" + idpage)
      },
      
      removeContext: function(){
        var cookies = _cp.readCookies();
        for (var cle in cookies) {
          if (cle.substring(0, 5) == "page-") {
            _cp.clearCookie(cle);
          }
        }
        
      }
      
    };
  }();
  
  Ext.EventManager.on(window, 'beforeunload', Atolcd.ContextMgr.saveContext);
  
}


Ext.apply(Atolcd.Right, {
  storeRigth: null,
  islocked: false,
  setOutilsRight: function(toolinit, islocked){
    this.storeRigth = new Ext.data.Store({
      reader: new Ext.data.JsonReader({
        id: 'codetypedroit',
        root: 'tools'
      }, [{
        name: 'codetypedroit'
      }, {
        name: 'iddroitmodalite',
        mapping: 'tdroitsprofils[0].iddroitmodalite',
        type: 'int'
      }])
    });
    this.storeRigth.loadData({
      tools: Ext.util.JSON.decode(toolinit)
    });
    if (islocked != 'false') {
      this.islocked = true;
    }
  },
  getOutilsRight: function(codeTypeDroit){
    if (this.storeRigth.getById(codeTypeDroit)) {
      if (islocked) {
        if (this.storeRigth.getById(codeTypeDroit).get('iddroitmodalite') > 20) {
          return 20;
        } else {
          return this.storeRigth.getById(codeTypeDroit).get('iddroitmodalite');
        }
      } else {
        return this.storeRigth.getById(codeTypeDroit).get('iddroitmodalite');
      }
    } else {
      return null;
    }
  },
  getIsLocked: function(){
    return this.islocked;
  }
});


// "correctif" pour ne pas reselectionner les lignes deja selectionnees
Ext.override(Ext.grid.RowSelectionModel, {
  selectAll: function(){
    if (this.isLocked()) {
      return;
    }
    
    for (var i = 0, len = this.grid.store.getCount(); i < len; i++) {
      if (!this.isSelected(i)) {
        this.selectRow(i, true);
      }
    }
    
    
    
  }
});


// fonction pour le tri numerique js
sortfunction = function(a, b){
  return (a - b);
}

// Fonction retournant un numero de disponible dans une liste.
// Utilise pour récuperer par exemple un numero de parcelle disponible.
// Prends en parametre les numeros existants, et éventuellement un numero à
// exclure.
Atolcd.getNumDispo = function(listeNumNonDispo, numToExclude){
  // Liste vide
  if (typeof(listeNumNonDispo) == 'undefined' || listeNumNonDispo.length == 0) {
    if (numToExclude == 1) {
      return 2;
    } else {
      return 1;
    }
  }
  
  // Trie par ordre numerique
  listeNumNonDispo.sort(sortfunction);
  
  if (typeof(numNotAllowed) == 'undefined') {
    numNotAllowed = null;
  }
  // Variables pour compairaison de continuité
  var oldNum = 0;
  var curNum = null;
  
  // On cherche une faille dans la continuitée des numero deja pris
  for (var i = 0; i < listeNumNonDispo.length; i++) {
    curNum = listeNumNonDispo[i];
    
    // si première boucle, on compare avec 0
    
    if ((curNum - oldNum) > 1) // La différence entre le nombre d'avant
    // et celui sup à 1, il y a donc faille
    // (on enleve le cas où les nombres sont
    // identiques).
    {
      // Avant de retourner le numero, on regarde si c'est pas celui non
      // autorisé.
      if ((oldNum + 1) == numToExclude) {
        oldNum = oldNum + 1;
      } else {
        return (oldNum + 1);
      }
    } else {
      // Nombre continue, on passe au suivant.
      oldNum = curNum;
    }
  }
  
  // On arrive ici, cela signifie que la liste des numero est continue. On
  // retourne le dernier, +1.
  if ((listeNumNonDispo[listeNumNonDispo.length - 1] + 1) == numNotAllowed) {
    return (listeNumNonDispo[listeNumNonDispo.length - 1] + 2);
  } else {
    return (listeNumNonDispo[listeNumNonDispo.length - 1] + 1);
  }
}

// Fonction contains d'un tableau, avec en plus le nbOcc minimum necessaire pour
// renvoyer vrai.
// Utilisé par exemple pour savoir si une valeur est en doublont dans un tableau
Atolcd.contains = function(tab, value, nbOcc){
  if (typeof(nbOcc) == 'undefined') {
    nbOcc = 1;
  }
  
  var nbOccValeur = 0;
  for (var i = 0; i < tab.length; i++) {
    if (tab[i] === value) { // La valeur est dans le tableau
      nbOccValeur += 1;// On incrémente le nombre d'occurence dans ce tableau
      if (nbOccValeur == nbOcc) // On regarde si le nombre d'occurence necesaire
      // demandée est ok
      {
        return true;
      }
    }
  }
  return false;
}

// retourne la liste des numero de parcelles pris, avec éventuellement en
// parametre un ilot a exclure de cette liste.
// utile dans le cas d'une edition d'ilot par exemple.
Atolcd.getNumParcellesNonDispo = function(scope, callback, idIlotToExclude){
  var listeNumNonDispo = new Array();
  
  // On charges les numero de parcelles non disponibles
  Ext.Ajax.request({
    url: 'request/listeNumParcelleExploit.php',
    method: 'GET',
    success: function(result, request){
    
      var myResponse = eval(result.responseText);
      if (myResponse != null) {
        if (myResponse.length > 0) {
          listeNumNonDispo = myResponse;
          // Vérification du type tableau pour la sortie
          if (typeof(listeNumNonDispo) == 'undefined') {
            listeNumNonDispo = new Array();
          }
          
          
          
        } else {
          listeNumNonDispo = new Array();
        }
        Ext.callback(callback, scope, [listeNumNonDispo]);
      }
      
    },
    params: {
      idilot: idIlotToExclude
    }
  });
}

// Retourne un trait quand la valeur est vide (chaine de caractere vide,
// spécifique aux valeurs nulles des record.

Atolcd.renderer.nullDash = function(renderer){
  return function(value, metadata, record, rowIndex, colIndex, store){
    var res = null;
    if (renderer != null) {
      res = renderer(value, metadata, record, rowIndex, colIndex, store)
    } else {
      res = value;
    }
    
    if (res == '') {
      return "-";
    } else {
      return res;
    }
  }
}

// Permet d'ajouter un tooltip sur une cellule, possedant déja un renderer, ou
// pas.
toolTip_Renderer = function(renderer){
  return function(value, metadata, record, rowIndex, colIndex, store){
    var res = null;
    if (renderer != null) {
      res = renderer(value, metadata, record, rowIndex, colIndex, store)
    } else {
      res = value;
    }
    if (value != null){
      metadata.attr = 'ext:qtip = "'+res+'"';
    }
    return res;
  }
}

// -- SHOW FIRST :
// Elements relatifs au show first, fonction permettant dans une grid de ne pas
// repeter certaines valeurs, suivant un field de regroupement.
// Les colonnes peuvent rester triables.


// Renderer qui permet de ne pas repeter visuellement des valeurs, regroupées
// par un champ groupfield.
// Peux prendre en plus le currentField, afin d'ajouter une vérification sur le
// champ actuel, de manière à l'afficher si
// sa valeur change en étant pourtant dans un meme regroupement.
// Peut prendre un renderer en sus.
Atolcd.renderer.showFirst = function(groupField, currentField, renderer){
  return function(value, metadata, record, rowIndex, colIndex, store){
    if (renderer != null) {
      value = renderer(value, metadata, record, rowIndex, colIndex, store);
    }
    var recordPrec = store.getAt(rowIndex - 1);
    var recordCourant = store.getAt(rowIndex);
    
    // Pas de ligne précedente, on affiche dans tous les cas.
    if (recordPrec == null) {
      return value;
    }
    
    // On a un record precedent.
    if (recordCourant.get(groupField) !== recordPrec.get(groupField)) {
      // On affiche soit parce que groupField a changé
      return value;
    } else if (currentField !== null && recordCourant.get(currentField) !== recordPrec.get(currentField)) {
      // On affiche soit parce que la valeur a changé
      return value;
    } else {
      // Sinon on affiche pas
      return "";
    }
  }
};

// Renvoi une classe css sur le premier d'un groupe, groupe étant défini par un
// champs.
// Ne pas oublier enableRowBody = true dans la config de la vue.
showFirst_getRowClass = function(groupField, cssClass, otherRowClassGetter){
  return function(record, index, rowParams, store){
    if (otherRowClassGetter != null) {
      cssClass += ' ' + otherRowClassGetter(record, index, rowParams, store);
    }
    
    var recordPrec = store.getAt(index - 1);
    var recordCourant = record;
    
    // Pas de ligne précedente, on affiche dans tous les cas.
    if (recordPrec == null) {
      return "";
    }
    
    // On a un record precedent.
    if (recordCourant.get(groupField) === recordPrec.get(groupField)) {
      // Le groupField est pareil, on ne renvoie pas de css spécifique.
      return "";
    } else {
      return cssClass;
    }
  }
};

// Renderer showfirst pour un rowAction (n'affiche que le premier d'un groupe).
// Attention, doit etre ajouté post création du rowaction.
showFirst_rowAction = function(detailActionRow, groupField){
  return function(value, cell, record, row, col, store){
    var recordPrec = store.getAt(row - 1);
    var recordCourant = record;
    
    // Pas de ligne précedente, on affiche dans tous les cas.
    if (recordPrec == null) {
      cell.css += (cell.css ? ' ' : '') + 'ux-row-action-cell';
      return this.tpl.apply(this.getData(value, cell, record, row, col, store));
    }
    
    // On a un record precedent.
    if (recordCourant.get(groupField) === recordPrec.get(groupField)) {
      // Le groupField est pareil, on ne renvoie pas de css spécifique.
      return "";
    } else {
      cell.css += (cell.css ? ' ' : '') + 'ux-row-action-cell';
      return this.tpl.apply(this.getData(value, cell, record, row, col, store));
    }
  }
.createDelegate(detailActionRow);
}

// En ajoutant l'option hideWithLabel à true sur les objet field d'ext, cela
// permet de cacher ou afficher le label de ces field, lorsqu'on est dans un
// panel de type form.
Ext.override(Ext.form.Field, {
  show: function(){
    if (this.fireEvent("beforeshow", this) !== false) {
      this.hidden = false;
      if (this.autoRender) {
        this.render(typeof this.autoRender == 'boolean' ? Ext.getBody() : this.autoRender);
      }
      if (this.rendered) {
        var r = this.getEl().up('div.fake-x-form-item');
        if (this.hideWithLabel === true && !Ext.isEmpty(r)) {
          // class temporaire utilisée pour affichage (suppression margin/padding)
          r.replaceClass('fake-x-form-item', 'x-form-item');
          r.dom.firstChild.firstChild.nodeValue = String.format('{0}', this.fieldLabel + (this.labelSeparator || ':'));
          r.setHeight(this.height || 22);
        }
        this.onShow();
      }
      this.fireEvent("show", this);
    }
    return this;
  },
  hide: function(){
    if (this.fireEvent("beforehide", this) !== false) {
      this.hidden = true;
      if (this.rendered) {
        var r = this.getEl().up('div.x-form-item');
        if (this.hideWithLabel === true && !Ext.isEmpty(r)) {
          // class temporaire utilisée pour affichage (suppression margin/padding)
          r.replaceClass('x-form-item', 'fake-x-form-item');
          r.dom.firstChild.firstChild.nodeValue = String.format('{0}', '');
          r.setHeight(0);
        }
        this.onHide();
      }
      this.fireEvent("hide", this);
    }
    return this;
  }
});

Ext.isIE8 = Ext.isIE && /msie 8/.test(navigator.userAgent.toLowerCase());

/**
 * Mask de chargement sous forme de fenetre car cela permet :
 * _qu'il soit centré au milieu de fenetre
 * _qu'il mask completement toute la page
 * Message personnalisable via la fonction setMsg(string).
 */
Atolcd.mask = new Ext.Window({
  hidden: true,
  modal: true,
  width: 170,
  shadow: false,
  autoHeight: true,
  plain: true,
  bodyStyle: 'padding: 5px;',
  closeAction: 'hide',
  closable: false,
  setMsg: function(msg){
    this.msg = msg;
  },
  msg: 'Veuillez patienter...',
  items: [{
    xtype: 'label',
    cls: 'backgroundPainted'
  }],
  bodyBorder: false,
  listeners: {
    scope: this,
    show: function(cpt){
      cpt.items.items[0].setText("<img src='/portail_base/img/extjs/grid/loading.gif'/> " + cpt.msg, false);
      cpt.center();
    }
  }
});


/**
 * popup permettant d'afficher une information pendant un temps donné.
 * @param {String} msg : message à afficher dans la fenêtre
 * @param {Integer} delay : delai avant fermeture
 */
Atolcd.popup = function(msg, delay){
  Atolcd.popinfo = new Ext.Window({
    hidden: true,
    modal: true,
    width: 170,
    shadow: false,
    autoHeight: true,
    plain: true,
    bodyStyle: 'padding: 5px;',
    closeAction: 'hide',
    closable: false,
    setMsg: function(msg){
      this.msg = msg;
    },
    items: [{
      xtype: 'label',
      cls: 'backgroundPainted'
    }],
    bodyBorder: false,
    listeners: {
      scope: this,
      show: function(popup){
        if (Ext.isEmpty(delay)){
          delay = 2000;
        }
        popup.items.items[0].setText(msg, false);
        popup.hide.defer(delay, popup);
      }
    }
  });
  return Atolcd.popinfo;
}

/**
 * Permet d'arrondir un chiffre a X nombre aprés la virgule
 * 
 * @param {Object} value
 * @param {Object} precision
 */
Atolcd.roundFloat = function(value, precision)
{
  return Math.round(value * Math.pow(10,precision)) / Math.pow(10,precision);
}

/**
 * Renderer d'un nombre sous forme de valeur a 4décimale enchainé du symbole euro
 * si la valeur passée n'est pas un nombre ou une chaine pouvant être parser, cette méthode retournera un NaN
 * @param {Number} v valeur de départ
 */
Ext.util.Format.frMoney4d = function(v){
    v = (Math.round((v-0)*10000))/10000;
    v = String((v).toFixed(4));
    var ps = v.split('.');
    var whole = ps[0];
    var sub = ps[1] ? '.'+ ps[1] : '.00';
    var r = /(\d+)(\d{3})/;
    while (r.test(whole)) {
        whole = whole.replace(r, '$1' + ' ' + '$2');
    }
    v = whole + sub;
    if(v.charAt(0) == '-'){
        return '-' + v.substr(1)+' €';
    }
    return  v+" €";
}

/**
 * Petite fonction pour simplifier un renderer de colonne avec une valeur sur 2 décimales
 * @param {Number} value
 */
Atolcd.renderer.renderFloat2d = function(value){
  return Atolcd.roundFloat(value, 2);
}
