
// object (new) that handles resizing of an element
const Resizable = function (element, params)
{
  const prefix = 'zero.ui-resizable.';
  const cacheKey = prefix + (params.save || 'none');
  const resizingClass = 'ui-resizing';

  let isVertical = ['Y', 'y'].indexOf(params.axis) > -1;

  this.element = element;
  this.params = params;
  this.handle = this.element.querySelector(this.params.handle || '.handle');

  if (!this.handle)
  {
    throw 'Set the [handle] parameter to a valid CSS selector within the attached element';
  }


  // binds events to the handle so the resizing works
  this.listen = () =>
  {
    this.handle.addEventListener('mousedown', this.start);
    this.handle.addEventListener('dblclick', this.reset);
  };


  // detaches the resizable
  this.detach = () =>
  {
    this.handle.removeEventListener('mousedown', this.start);
    this.handle.removeEventListener('dblclick', this.reset);
    document.removeEventListener('mousemove', this.resize);
    document.removeEventListener('mouseup', this.stop);
  };


  // start resizing of an element
  this.start = (e) =>
  {
    this.coordinates = {
      X: e.pageX,
      Y: e.pageY,
      offsetX: 0,
      offsetY: 0
    };
    document.body.classList.add(resizingClass);
    document.addEventListener('mousemove', this.resize);
    document.addEventListener('mouseup', this.stop);
  };


  // resize the element
  this.resize = (e) =>
  {
    let deltaX = e.pageX - this.coordinates.X;
    let deltaY = e.pageY - this.coordinates.Y;
    let delta = isVertical ? deltaY : deltaX;
    let newValue = this.value + delta;

    if (params.min && params.min > newValue)
    {
      newValue = params.min;
    }
    else if (params.max && params.max < newValue)
    {
      newValue = params.max;
    }

    this.update(newValue);
  };


  // stop resizing and unbind listeners
  this.stop = (e) =>
  {
    document.body.classList.remove(resizingClass);
    document.removeEventListener('mousemove', this.resize);
    document.removeEventListener('mouseup', this.stop);

    this.value = getCurrentValue();

    localStorage.setItem(cacheKey, this.value);
  };


  // updates dimension of the target element
  this.update = value =>
  {
    if (value > 0)
    {
      this.element.style[isVertical ? 'height' : 'width'] = value + 'px';
    }
  };


  // resets to the original value
  this.reset = () =>
  {
    localStorage.removeItem(cacheKey);
    this.element.style[isVertical ? 'height' : 'width'] = '';
    this.value = getCurrentValue();
  };


  // get current size value from element
  let getCurrentValue = () =>
  {
    return this.element[isVertical ? 'clientHeight' : 'clientWidth'];
  };

  this.value = getCurrentValue();


  // use cached value on load
  if (params.save)
  {
    const newValue = +localStorage.getItem(cacheKey);

    if (newValue > 0)
    {
      this.update(+localStorage.getItem(cacheKey));
      this.value = newValue;
    }
  }
};

/**
 * resize an element
 */
export default {
  bind(el, binding)
  {
    let resizable = new Resizable(el, binding.value);
    resizable.listen();
  }
};