/**
 * Mousey Index
 * @module src/index.jsx
 */

import { initializeDOM } from "./utility/index.js";

// We will build 100 elements
let elementCount = 100;

// Keep track of current element offset
let currentIndex = 0;

// Set when we're done
let almostDone = 0;

// Append a bunch of elements
let elements = [];

// Keep track of coordinates
let coordinates = [];

/**
 * Start the application and bind events
 */
function initialize() {
  initializeDOM();
  makeElements();
  window.addEventListener("mousemove", handleMouseMove);
  window.addEventListener("click", handleClick);
  animate();
}

/**
 * Animate the divs
 */
function animate(time) {
  requestAnimationFrame(animate);
  updateElements(time);
}

/**
 * Update one element
 */
function updateElement({ element, coordinate, percent, time }) {
  // Slow down time!
  time /= 100;

  // Set the color, size, and position
  let hue = Math.round((percent * 360 + time) % 360);
  let size = (Math.cos(percent * 10 + time / 30) + 1 / 2) * 50;

  let xpos = coordinate.pageX + Math.sin(percent + time / 30) * 20;
  let ypos = coordinate.pageY + Math.cos(percent + time / 30) * 20;

  // Update the element
  element.style.width = size + "px";
  element.style.height = size + "px";
  element.style.left = xpos + "px";
  element.style.top = ypos + "px";
  element.style.background = `hsl(${hue}deg 100% 50%)`;
}

/**
 * Update the current element positions
 */
function updateElements(time) {
  // Loop over all the elements
  for (let index = 0; index < coordinates.length; index += 1) {
    // Get the element index offset by the current index
    let elementIndex =
      (index - currentIndex + coordinates.length) % coordinates.length;

    // Get the next DIV and update it
    let element = elements[elementIndex];
    let coordinate = coordinates[elementIndex];

    // Convert the index to a value between 0..1
    let percent = elementIndex / elementCount;

    updateElement({ element, coordinate, percent, time });
  }
}

function handleClick() {
  almostDone = 0;
}

/**
 * Handle when we click on the page
 */
function handleMouseMove(event) {
  // Get the mouse coordinates
  const { pageX, pageY } = event;
  appendCoordinate({ pageX, pageY });
}

/**
 * Append a coordinate to the rotating list
 */
function appendCoordinate({ pageX, pageY }) {
  if (almostDone > elementCount) return;
  coordinates[currentIndex] = { pageX, pageY };
  currentIndex = (currentIndex + 1) % elementCount;
  almostDone += 1;
}

/**
 * Make a bunch of DOM elements
 */
function makeElements() {
  for (let index = 0; index < elementCount; index++) {
    let element = makeElement();
    elements.push(element);
  }
}

/**
 * Make a DOM element
 */
function makeElement() {
  let element = document.createElement("div");
  element.style.position = "absolute";
  element.style.transform = "translate3d(-50%, -50%, 0)";
  document.body.appendChild(element);
  return element;
}

// Run the application
initialize();
