blockchainExplorer = function(){

  // Init array
  var liste_blocks   = null;
  var flag_nav       = true;
  var classes        = ['bg-grey-even','bg-grey-odd'];
  var cur_class      = 0;
  var cur_height     = [];
  var cur_methode    = 'hasard';
  var isInitSelector = false;
  var _mode          = 1;

  function _precisionRound(number) {
      var precision = 4;
      var factor = Math.pow(10, precision);
      return Math.round((number/100000000) * factor) / factor;
  }

  function _getblockNameFromHash(hash)
  {
    var retour = '';
    if (liste_blocks != null)
      liste_blocks.forEach(function(item){
        if (hash == item.hash) retour = item.name;
      });
    return retour;
  }

  function _getblocHashFromName(name)
  {
    var retour = '';
    liste_blocks.forEach(function(item){
      if (name == item.name) retour = item.hash;
    });
    return retour;
  }

  function _addInfoForBlock(block)
  {
    var contenu = '';
    var downloadingImage = new Image();

    cur_height.push(block.height);
    
    cur_class  = 1 - cur_class;

    blockName = _getblockNameFromHash(block.hash);
    if (blockName != '') blockName = ' ( '+blockName+' )';
      
    contenu += '      <div style="height:220px;width:100%;display:block;position:absolute">';
    if (_mode != 0)
    {
      contenu += '<div style="color:black;opacity:1.0;margin-right:30px">';
      // contenu += '      <h2> <span style="font-size:12px">block</span> '+block.height+blockName+'</h2>';
      //contenu += '<span style="font-size:4px">&nbsp;</span>';
      contenu += '      <table width="100%" style="margin-top:12px">';
      //contenu += '       <tr><td>hash</td><td align="right"><b>'+block.hash+'</b></td></tr>';
      //contenu += '       <tr><td>index</td><td align="right"><b>'+block.block_index+'</b></td></tr>';
      contenu += '        <tr><td>timestamp</td><td align="right"><b>'+block.time+'</b></td></tr>';
      contenu += '        <tr><td>nonce</td><td align="right"><b>'+block.nonce+'</b></td></tr>';
      contenu += '        <tr><td>nb tx</td><td align="right"><b>'+block.n_tx+'</b></td></tr>';
      contenu += '        <tr><td>outputs</td><td align="right"><b>'+_precisionRound(block.topisto_outputs).toFixed(4)+'</b></td></tr>';
      contenu += '        <tr><td>inputs</td><td align="right"><b>'+_precisionRound(block.topisto_inputs).toFixed(4)+'</b></td></tr>';
      contenu += '        <tr><td>fees</td><td align="right"><b>'+_precisionRound(block.topisto_fees).toFixed(4)+'</b></td></tr>';
      contenu += '        <tr><td>reward</td><td align="right"><b>'+_precisionRound(block.topisto_reward).toFixed(4)+'</b></td></tr>';
      contenu += '      </table>';
      contenu += '</div>';
    }
    contenu += '      </div>';

    $('#info_'+block.height).html(contenu);

    contenu = '';
    contenu += '<div id="img_'+block.height+'" style="';
    contenu += 'height:220px;';
    contenu += 'content: "";';
    contenu += 'top: 0;';
    contenu += 'left: 0;';
    contenu += 'bottom: 0;';
    contenu += 'right: 0;';
    contenu += 'position: relative;';
    contenu += 'z-index: -1;   ';
    contenu += '"></div>'

    $('#info_'+block.height).append(contenu);

    downloadingImage.onload = function(){

      // $('#img_'+block.height).attr('src', this.src);   
/*
      $('#img_'+block.height).attr('height', _height);
      $('#img_'+block.height).attr('width','auto');
*/

      var div0 = document.getElementById('img_'+block.height);

      div0.style.backgroundImage = "url(" + this.src + ")";
      div0.style.backgroundRepeat = "no-repeat";
      div0.style.backgroundPosition = "center";
      div0.style.backgroundSize = "auto 100%";
      if (_mode==1) div0.style.opacity=0.3;

      flag_nav = true;
    };
    downloadingImage.src = 'images/block_image.php?methode='+cur_methode+'&hash='+block.hash;

    return true;
  }

  function _addDiv(block_height)
  {
    var contenu = '';

    contenu += '<div id="block_'+block_height+'" class="container-fluid '+classes[cur_class]+'">';
    contenu += '  <div class="row">';
    contenu += '###BLOCK_DESC###';
    contenu += '  </div>';
    contenu += '</div>';

    return contenu;
  }

  function _addDivForBlock(block_height)
  {
    var contenu = _addDiv(block_height);
    var block_desc = '';

    block_desc += '    <div class="col-sm-12" id="info_'+block_height+'">';
    block_desc += '      <h2>BLOCK '+block_height+' ...</h2>';
    block_desc += '    </div>';

    $('#blockchain').append(contenu.replace('###BLOCK_DESC###',block_desc));

    return true;
  }

  function _addDivForVoid()
  {
    return _addDivForBlock('void');
  }

  function _toggleForwardBtn()
  {
    if (cur_height.length < 3)
    {
      $('#fast_forward_btn').removeClass('btn-success');
      $('#fast_forward_btn').addClass('btn-secondary');
      $('#btn-forward').removeClass('btn-info');
      $('#btn-forward').addClass('btn-secondary');
    } else {
      $('#fast_forward_btn').removeClass('btn-secondary');
      $('#fast_forward_btn').addClass('btn-success');
      $('#btn-forward').removeClass('btn-secondary');
      $('#btn-forward').addClass('btn-info');
    }
    return true;      
  }

  function _gotoBlock(block_name)
  {
    $(document).scrollTop( $("#explorer").offset().top );
    // Bloquer la navigation pendant le calcul
    if (!flag_nav)
    {
      window.alert('A block image is currently computed, please wait ...');
      return false;
    }
    flag_nav   = false;

    if (block_name == 'NEXT')
    {
      flag_nav   = true;

      // Supprimer un block
      if (cur_height.length < 3)
      {
        window.alert('No Next Block, you are at '+$('#blockSelector').val()+' block !');
        return false;
      }

      liste_blocks['PREVIOUS'] = liste_blocks['BLOCK_'+cur_height[cur_height.length-1]];
      cur_height.pop();
        
      _toggleForwardBtn();

      $('#block_'+cur_height[cur_height.length-2]).slideDown(400, function() {
        // Animation complete.
        $('#blockchain').children('div:last').remove();
        cur_class = 1 - cur_class;
      });

    } else {
      // Ajouter un block
      _addDivForBlock(cur_height[cur_height.length-1] - 1);

      // Décaler d'un block vers le haut
      if (cur_height.length > 1) $('#block_'+cur_height[cur_height.length-2]).slideUp();

      block_hash = '';
      if (block_name != 'LAST') block_hash = '?block_hash='+liste_blocks[block_name];
      $.getJSON('data/getBlockInfo.php'+block_hash, function( data ) {
        liste_blocks['PREVIOUS'] = data.prev;
        liste_blocks['BLOCK_'+data.height] = data.hash;
        _addInfoForBlock(data);

        _toggleForwardBtn();
      });
    }

    return true;
  }

  function _ajouterTopBlock(data)
  {
    // Bloquer la navigation pendant le calcul
    if (!flag_nav) return false;
    flag_nav = false;

    // Ajouter un div
    _addDivForBlock(data.height);
    
    // Mettre les infos dans le div
     _addInfoForBlock(data);

    // Décaler le tableau cur_height par le haut
    cur_height.unshift(data.height);

    // Maintenir la liste des blocks
    liste_blocks['BLOCK_'+data.height] = data.hash;
  }

  function _ajouterPreviousBlock()
  {
    // Bloquer la navigation pendant le calcul
    if (!flag_nav) return false;
    flag_nav = false;

    // Ajouter un div
    _addDivForBlock(cur_height[cur_height.length-1] - 1);
    
    // Mettre les infos du
    block_hash = '?block_hash='+liste_blocks['PREVIOUS'];
    $.getJSON('data/getBlockInfo.php'+block_hash, function( data ) {
      liste_blocks['PREVIOUS'] = data.prev;
      liste_blocks['BLOCK_'+data.height] = data.hash;
      _addInfoForBlock(data);
    });
  }

  function _initBlockchain(block_name)
  {
    $(document).scrollTop( $("#explorer").offset().top );
    $('#blockchain').html('');
    cur_height = [];
    cur_class  = 0;
    flag_nav   = true;

    block_hash = '';
    if (block_name != 'LAST') block_hash = '?block_hash='+_getblocHashFromName(block_name);
    $.getJSON('data/getBlockInfo.php'+block_hash, function( data ) {
      _addDivForBlock(data.height);        
      _addInfoForBlock(data);

      liste_blocks['PREVIOUS'] = data.prev;
      if (data.prev != '0000000000000000000000000000000000000000000000000000000000000000')
        _gotoBlock('PREVIOUS');
      else 
        _addDivForVoid();
      
      // Ajouter le trigger sur les nouveaux blocks
      if (block_name == 'LAST') 
        blockchainListener.addBlockHook(_ajouterTopBlock);

    });

    return true;
  }

  function _blockSelectorChange()
  {
    _initBlockchain($('#blockSelector').val());
    $('#fast_forward_btn').attr('data-original-title', $('#blockSelector').val());
  }

  function _initBlockSelector()
  {
    if (!isInitSelector)
    {
      // Init the selector
      var select = $('#blockSelector');
      
      $.each(liste_blocks, function (key, bloc) {
        select.append(new Option(bloc.name, bloc.name));
      });

      isInitSelector = true;
    }
  }

  function _init(mode = 1)
  {
    _mode = mode;
    cur_height     = [];

    $.getJSON('data/getKnownBlocksList.php', function( data ) {
      liste_blocks =  data;
      _initBlockSelector();
      if (cur_height.length == 0) _initBlockchain('LAST');
      return true;
    });
  }

  return {

    ajouterPreviousBlock: _ajouterPreviousBlock,
    getblocHashFromName: _getblocHashFromName,
    ajouterTopBlock : _ajouterTopBlock,

    init: _init
  };
}();