import NileSlider from '../nile-slider';
import { NileSliderEvents } from '../types/nile-slider.enums';

export const getClampedPercent = (
  rect: DOMRect,
  x: number,
): number => {
  const clampedX = Math.max(0, Math.min(x, rect.width)); 
  const percent = (clampedX / rect.width) * 100;
  return percent;
};

export const percentToValue = (percent: number, nileSlider: NileSlider): number => {
  const value = nileSlider.minValue + (percent / 100) * (nileSlider.maxValue - nileSlider.minValue);
  if(nileSlider.maxValue - nileSlider.minValue < 1) {
    return parseFloat(value.toFixed(2));
  } else {
    return Math.floor(value);
  }
};

export const valueToPercent = (value: number, nileSlider: NileSlider): number => {
  return ((value - nileSlider.minValue) / (nileSlider.maxValue - nileSlider.minValue)) * 100;
};

export const handleSingleSlider = (
  e: MouseEvent,
  rect: DOMRect,
  nileSlider: NileSlider
): void => {
  const x = e.clientX - rect.left;
  const percent = getClampedPercent(rect, x);
  nileSlider.value = percentToValue(percent, nileSlider);
  nileSlider.emit(NileSliderEvents.NILE_CHANGE, { value: nileSlider.value });
  nileSlider.buttonOne.style.left = `${percent}%`;
  nileSlider.completed.style.width = `${percent}%`;
};

export const handleRangeOne = (
  e: MouseEvent,
  rect: DOMRect,
  nileSlider: NileSlider
): void => {
  const x = e.clientX - rect.left;
  const percent = getClampedPercent(rect, x);
  nileSlider.rangeOneValue = percentToValue(percent, nileSlider);
  nileSlider.rangeOneValue = Math.min(nileSlider.rangeOneValue, nileSlider.rangeTwoValue);
  nileSlider.emit(NileSliderEvents.NILE_BUTTON_FIRST_CHANGE, {
    value: nileSlider.rangeOneValue,
  });
  if (nileSlider.rangeTwoValue > nileSlider.rangeOneValue) {
    nileSlider.buttonOne.style.left = `${percent}%`;
  }
};

export const handleRangeTwo = (
  e: MouseEvent,
  rect: DOMRect,
  nileSlider: NileSlider
): void => {
  const x = e.clientX - rect.left;
  const percent = getClampedPercent(rect, x);
  nileSlider.rangeTwoValue = percentToValue(percent, nileSlider);
  nileSlider.rangeTwoValue = Math.max(nileSlider.rangeTwoValue, nileSlider.rangeOneValue);
  nileSlider.emit(NileSliderEvents.NILE_BUTTON_LAST_CHANGE, {
    value: nileSlider.rangeTwoValue,
  });

  if (nileSlider.rangeTwoValue > nileSlider.rangeOneValue) {
    nileSlider.buttonTwo.style.left = `${percent}%`;
  }
};

export const getHtmlElements = (nileSlider: NileSlider) => {
  nileSlider.range = nileSlider.renderRoot.querySelector('.range') as HTMLElement;
  nileSlider.buttonOne = nileSlider.renderRoot.querySelector('.range-button') as HTMLElement;
  nileSlider.buttonTwo = nileSlider.renderRoot.querySelector('.range-button-two') as HTMLElement;
  nileSlider.completed = nileSlider.renderRoot.querySelector('.range-completed') as HTMLElement;

  nileSlider.range.addEventListener('mousedown', nileSlider.onMouseDown);

  nileSlider.buttonOne?.addEventListener('mousedown', () => {
    nileSlider.activeThumb = 'one';
    addMoveListeners(nileSlider);
  });

  nileSlider.buttonTwo?.addEventListener('mousedown', () => {
    nileSlider.activeThumb = 'two';
    addMoveListeners(nileSlider);
  });
};

export const addMoveListeners = (nileSlider: NileSlider): void => {
  window.addEventListener('mousemove', nileSlider.onMouseMove);
  window.addEventListener('mouseup', nileSlider.onMouseUp);
};

export const removeMoveListeners = (nileSlider: NileSlider): void => {
  window.removeEventListener('mousemove', nileSlider.onMouseMove);
  window.removeEventListener('mouseup', nileSlider.onMouseUp);
};

export const handleTwoThumbClick = (
  value: number,
  nileSlider: NileSlider
): void => {
  const distToOne = Math.abs(value - nileSlider.rangeOneValue);
  const distToTwo = Math.abs(value - nileSlider.rangeTwoValue);

  if (distToOne <= distToTwo) {
    const clamped = Math.min(value, nileSlider.rangeTwoValue);
    nileSlider.rangeOneValue = nileSlider.checkValueValidity(clamped, nileSlider.minValue, nileSlider.maxValue);
  } else {
    const clamped = Math.max(value, nileSlider.rangeOneValue);
    nileSlider.rangeTwoValue = nileSlider.checkValueValidity(clamped, nileSlider.minValue, nileSlider.maxValue);
  }  

  const percentOne = valueToPercent(nileSlider.rangeOneValue, nileSlider);
  const percentTwo = valueToPercent(nileSlider.rangeTwoValue, nileSlider);

  nileSlider.buttonOne.style.left = `${percentOne}%`;
  nileSlider.buttonTwo.style.left = `${percentTwo}%`;

  const left = Math.min(percentOne, percentTwo);
  const width = Math.abs(percentTwo - percentOne);

  nileSlider.completed.style.left = `${left}%`;
  nileSlider.completed.style.width = `${width}%`;

  nileSlider.emit(NileSliderEvents.NILE_BUTTON_FIRST_CHANGE, {
    value: nileSlider.rangeOneValue,
  });
  nileSlider.emit(NileSliderEvents.NILE_BUTTON_LAST_CHANGE, {
    value: nileSlider.rangeTwoValue,
  });
};
