import LineHeatmap from "./lineHeatmap";
import "nouislider";

const template = `<div>
  <div class="line-heatmap-controls">
    <div id="line-heatmap-slider"></div>
  </div>
  <div id="line-heatmap-canvas">
    <div id="line-heatmap-view"></div>
    <div id="line-heatmap-tooltip"></div>
  </div>
</div>
`;

const cursorDist = 10;

const stateObject = {};

let x1, y1, x2, y2;
let firstClick = true;
let div = null;

let posLeft;
let posTop;
let yBottom;
let xBottom;

function init (elementId, logString, useTooltip = false, config = {}) {
  const el = document.getElementById(elementId);
  el.innerHTML = template;
  const logData = logTransform(logString);
  // create container
  const heatmap = new LineHeatmap('line-heatmap-view');
  heatmap.create(config);
  heatmap.setTrackData(logData);

  const html5Slider = document.getElementById('line-heatmap-slider');
  noUiSlider.create(html5Slider, {
      start: [1, logData.length],
      connect: true,
      step: 1,
      margin: 1,
      range: {
          'min': 1,
          'max': logData.length
      }
  });
  
  stateObject['container'] = el;
  stateObject['heatmap'] = heatmap;
  stateObject['data'] = logData;
  stateObject['slider'] = html5Slider;

  if (useTooltip) {
    registerClickEvent();
    const canvasWrapper = document.getElementById('line-heatmap-canvas');
    const tooltip = document.getElementById('line-heatmap-tooltip');
    function updateTooltip (x, y, value) {
      const transl = `translate(${x + cursorDist}px, ${y + cursorDist}px)`;
      tooltip.style.webkitTransform = transl;
      tooltip.innerHTML = `(${x},${y},${value})`;
    };

    canvasWrapper.onmousemove = function (ev) {
      var x = ev.layerX;
      var y = ev.layerY;
      // getValueAt gives us the value for a point p(x/y)
      var value = stateObject['heatmap'].instance.getValueAt({
        x: x, 
        y: y
      });
      tooltip.style.display = 'block';
      updateTooltip(x, y, value);
    };
    // hide tooltip on mouseout
    canvasWrapper.onmouseout = function() {
      tooltip.style.display = 'none';
    };
    /* tooltip code end */
  }

  html5Slider.noUiSlider.on('update', function (values, handle) {
    const logValues = this.get();
    const newData = stateObject['data'].slice(+logValues[0]-1, +logValues[1] + 1);
    stateObject['heatmap'].setTrackData(newData);
    if(div !== null)
      updateDivText(div, posLeft, posTop, xBottom, yBottom);
  });
}

function updateLogString (logString) {
  const logData = logTransform(logString);
  stateObject['data'] = logData;
  stateObject['slider'].noUiSlider.updateOptions({
    range: {
        'min': 1,
        'max': logData.length
    }
  });
  stateObject['heatmap'].setTrackData(logData); 
}

function countClicks (x1, y1, x2, y2) {
  const instance = stateObject['heatmap'].instance;
  const points = instance.getData().data;
  let counter = 0;
  for(let i = 0; i < points.length; ++i) {
    const point = points[i];
    if (point.x >= x1 && point.y >= y1) {
      if (point.x <= x2 && point.y <= y2) {
        counter += point.value;
      }
    }
  }
  return counter;
}

function getClicksInWindow (x1, y1, x2, y2) {
  const instance = stateObject['heatmap'].instance;
  const points = instance.getData().data;
  const list = [];
  for(let i = 0; i < points.length; ++i) {
    const point = points[i];
    if (point.x >= x1 && point.y >= y1) {
      if (point.x <= x2 && point.y <= y2) {
       list.push(point);
      }
    }
  }
  return list;
}

function totalClicks () {
  return stateObject['data'].length;
}

function getData () {
  return stateObject['data'];
}

function logTransform (logString) {
  const data = logString.split("\n")
  .filter(v => v.split(',').length > 3)
  .map(v => {
    const o = JSON.parse('[' + v + ']');
    return {
      x: o[0],
      y: o[1],
      value: 1
    };
  });
  return data;
}

function registerClickEvent () {
  const elemen = document.querySelector(".heatmap-canvas");
  window.onclick = function (evt) {
    if(evt.target !== elemen) {
      return;
    }
    if (firstClick) {
      if (evt.pageX || evt.pageY) {
        x1 = evt.pageX;
        y1 = evt.pageY;
      } else {
        x1 = evt.clientX + document.body.scrollLeft + elemen.scrollLeft;
        y1 = evt.clientY + document.body.scrollTop + elemen.scrollTop;
      }
      x1 -= elemen.offsetLeft;
      y1 -= elemen.offsetTop;
      firstClick = false;
    } else {
      if (evt.pageX || evt.pageY) {
        x2 = evt.pageX;
        y2 = evt.pageY;
      } else {
        x2 = evt.clientX + document.body.scrollLeft + elemen.scrollLeft;
        y2 = evt.clientY + document.body.scrollTop + elemen.scrollTop;
      }
      x2 -= elemen.offsetLeft;
      y2 -= elemen.offsetTop;

      firstClick = true;
      if (div !== null) {
        document.getElementById("line-heatmap-canvas").removeChild(div);
        div = null;
      }
      div = document.createElement("div");
      posLeft = Math.min(x1,x2);
      posTop = Math.min(y1,y2) - 585;
      yBottom = Math.max(y1,y2) - 585;
      xBottom = Math.max(x1,x2);
      const width = Math.abs(xBottom - posLeft);
      const height = Math.abs(yBottom - posTop);
      updateDivText(div, posLeft, posTop, xBottom, yBottom);
      div.style.width = width + "px";
      div.style.height = height + "px";
      div.style.position = "absolute";
      div.style.top = posTop + "px";
      div.style.left = posLeft + "px";
      div.style.border = "1px solid green";
      document.getElementById("line-heatmap-canvas").append(div);
      
    }
  }
}

function updateDivText (div, posLeft, posTop, xBottom, yBottom) {
  const count = countClicks(posLeft, posTop, xBottom, yBottom);
  const ratio = count/totalClicks();
  div.innerHTML = `<span style="font-size:14px">Quantidade de clicks: ${count}</span>
  <span style="font-size:14px">Proporção em relação ao total: ${ratio}</span>`;
}

function clicksEuclideanDist (points) {
  if(points.length <= 1) {
    return 0;
  } else if (points.length == 2) {
    const p1 = points[0];
    const p2 = points[1];
    return euclideanDist(p1, p2);
  } else {
    let count = 0;
    points.reduce((p1, p2) => {
      count += euclideanDist(p1, p2);
      return p2;
    });
    return count;
  }
}

function calcPixelsPerClick () {
  const data = getData();
  const totalPixels = clicksEuclideanDist(data);
  return totalPixels / totalClicks();
}

function calcPixelsPerClickInArea () {
  if(div == null) {
    return 0;
  }
  const data = getClicksInWindow(posLeft, posTop, xBottom, yBottom);
  const totalPixels = clicksEuclideanDist(data);
  return totalPixels / countClicks(posLeft, posTop, xBottom, yBottom);
}

function euclideanDist (p1, p2) {
  return Math.sqrt(Math.pow(p1.x-p2.x, 2) + Math.pow(p1.y-p2.y, 2));
}

export default {
  init,
  updateLogString,
  countClicks,
  totalClicks,
  getData,
  calcPixelsPerClick,
  calcPixelsPerClickInArea
}
