let lapiSliderInputBinding = {};
let sib = Shiny.inputBindings.getBindings().filter(el => el.binding.name === "shiny.sliderInput");

let percentInterpolator = (min, max) => (num) => (num - min) / (max - min) * 100; 


function addMarks(values, min, max, colors=null) {
        var html = '';
        var retorno = [];
        var left = 0;
        var left_p = "";
        let percent = percentInterpolator(min, max);
        var i;
        var marks = values.split(',').map(el => ({'a':el, 'b':percent(Number(el)) + '%'}));
        
        colors = colors !== null ? colors.split(",") : null;
        marks.forEach((el, idx) => {
          let sp = $('<span/>').attr('class', 'showcase__mark')
            .html(el.a).css('left', el.b).css('transform', 'translateX(-'+el.b+')');
          if(colors!==null) sp.css('background-color', colors[idx]);
          retorno.push(sp);
        });
       
        return retorno; //html; 
    }

function pct(min, max) {
  return a = +min, b = +max, size=Math.abs(b-a), function(t) {
    if(t<a || t>b) throw new Error("porcentagem: Valor fora do intervalo!");
    return (t-a)/size;
  };
}

function gradient(values, bt=1){
  var colors = ['#f95036','#ee8400','#d1ca1a','#32965d'].slice(0, values.length-1);
  if (Number(bt)===0) colors = colors.reverse();
  let ps = pct(values[0], values.slice(-1));
  let m = values.map(el => Math.round(ps(el)*100) + "%");
  return `linear-gradient(to right, ${colors.map((el, idx) => el+' '+m[idx]+', '+el+' '+m[idx+1]).join(',')})`;
}

function _background(data){
  data.slider.find('.irs-line')
      .css({'background':$(data).data('cordefundo')});
}

function _dblClick(data){
  return function(){
    data.secondInput.toggleClass('lapi-hidden');
    data.irsSingle.toggleClass('fa-edit');
    data.irsSingle.toggleClass('fa-times');
  }
}

function start(data){
  var self = $(this);
  var id = self.attr('id');
  data.mark = {
    values: self.attr('data-mark') || null,
    colors: self.attr('data-mark-colors') || null
  };
  data._min = self.attr('data-min');
  data._max = self.attr('data-max');
  data._grt_is_better = self.attr('data-grt-is-better');
  data.secondInput = $('#second-input-'+id);
  $('#'+id).on('change', function(evt){
    $('#second-input-'+id).prop('value', $(this).prop('value'));
  });
  data.sliderDiv = $('#lapislider-'+id);
  data.secondInputDiv = $('#lapislider-inputdiv-'+id);
  
  data.irsSingle = data.secondInputDiv.find('.lapi-icon-pull-right');
  data.irsSingle.click(_dblClick(data));
  data.secondInput.on('keypress', function(evt){
    if(evt.which == 13){
      
      $(data.input).data('ionRangeSlider').update({
        from:$(this).prop('value')
      });
      _background(data);
      data.irsSingle.toggleClass('fa-times');
      data.irsSingle.toggleClass('fa-edit');
      data.secondInput.addClass('lapi-hidden');
    } 
  });
  var setores = data.input.attr('setores');
  if(setores !== undefined && setores!==""){
    $(data).data('cordefundo', 
      gradient(setores.split(',').map(el => Number(el)), bt =self.attr('data-grt-is-better'))
    );
    _background(data);
  }
  if(data.mark.values !== null){
    let marks = addMarks(data.mark.values, data._min, data._max, data.mark.colors);
    $(data.slider).append(marks);
      
    if(marks.length > 1){    
        var po = $(marks[0]);
        var pt = $(marks[1]);
        if( Math.abs(Number(po.html()) - Number(pt.html())) < 12){
          pt.animate({
            top:'+=18px'
          });
        }
    }
      
    
  }
}


function getPos(el, dados){
  let self = $(el);
  let min = self.attr('data-min');
  let max = self.attr('data-max');
  let percent = percentInterpolator(min, max);
  return dados.map(el => ({'a':el, 'b':percent(Number(el)) + '%'}));
}


$.extend(lapiSliderInputBinding, sib[0].binding, {
  find:function(scope){
    // testa se o plugin está carregado
    if (!$.fn.ionRangeSlider){
      return [];
    }
    
    return $(scope).find('input.lapi-range-slider');
  },
  initialize: function(el){
    var self= this;
    var $el = $(el);
    $el.ionRangeSlider({
      onStart:start.bind(el),
      onUpdate:function(data){
        if(data.mark.values !== null){
    let marks = addMarks(data.mark.values, data._min, data._max, data.mark.colors);
    $(data.slider).append(marks);
      
    if(marks.length > 1){    
        var po = $(marks[0]);
        var pt = $(marks[1]);
        if( Math.abs(Number(po.html()) - Number(pt.html())) < 12){
          pt.animate({
            top:'+=18px'
          });
        }
    }}
        console.log(data);
      },
      onFinish: function(data){
      
      }
    });
  },
  receiveMessage: function(el, data){
    if (data.hasOwnProperty('marks')){
      if(!Array.isArray(data.marks)) data.marks = [data.marks]
      var id = $(el).attr('id');
      var marks = $('#lapislider-'+id).find('.showcase__mark');
      let pos = getPos(el, data.marks);
      marks.each(function(e){
        $(marks[e]).css('left', pos[e].b)
        $(marks[e]).html(pos[e].a);
      });
      for(var i = 0; i < marks.length-1; i++){
        var po = $(marks[i]);
        var pt = $(marks[i+1]);
        if((po.width() - Math.abs(po.position().left - pt.position().left)) > 1){
          if(po.position().top === pt.position().top){
            pt.animate({
              top:'+=18px'
            }); 
          }
        }else{
          if(po.position().top !== pt.position().top){
            pt.animate({
              top:'-=18px'
            }); 
          }
        }
      }
    }
    $(el).trigger('change'); 
  }
} );


Shiny.inputBindings.register(lapiSliderInputBinding);