/** Trading card aspect ratio (width / height). */
export const CARD_ASPECT_RATIO = 5 / 7;

/**
 * Layout math for a video element using CSS object-cover inside a container.
 */
export function computeObjectCoverLayout(videoWidth, videoHeight, containerWidth, containerHeight) {
  if (!videoWidth || !videoHeight || !containerWidth || !containerHeight) {
    return null;
  }

  const videoAspect = videoWidth / videoHeight;
  const containerAspect = containerWidth / containerHeight;

  let renderedWidth;
  let renderedHeight;
  let offsetX;
  let offsetY;

  if (videoAspect > containerAspect) {
    renderedHeight = containerHeight;
    renderedWidth = containerHeight * videoAspect;
    offsetX = (containerWidth - renderedWidth) / 2;
    offsetY = 0;
  } else {
    renderedWidth = containerWidth;
    renderedHeight = containerWidth / videoAspect;
    offsetX = 0;
    offsetY = (containerHeight - renderedHeight) / 2;
  }

  return {
    videoWidth,
    videoHeight,
    containerWidth,
    containerHeight,
    renderedWidth,
    renderedHeight,
    offsetX,
    offsetY,
  };
}

/** Map video-pixel bounds to percentage styles within an object-cover container. */
export function videoBoundsToContainerStyle(bounds, layout) {
  const {
    videoWidth,
    videoHeight,
    containerWidth,
    containerHeight,
    renderedWidth,
    renderedHeight,
    offsetX,
    offsetY,
  } = layout;

  const left = offsetX + (bounds.x / videoWidth) * renderedWidth;
  const top = offsetY + (bounds.y / videoHeight) * renderedHeight;
  const width = (bounds.width / videoWidth) * renderedWidth;
  const height = (bounds.height / videoHeight) * renderedHeight;

  return {
    left: `${(left / containerWidth) * 100}%`,
    top: `${(top / containerHeight) * 100}%`,
    width: `${(width / containerWidth) * 100}%`,
    height: `${(height / containerHeight) * 100}%`,
  };
}

/** Centered card guide frame in container pixel coordinates. */
export function computeCardGuideBounds(containerWidth, containerHeight) {
  let width = containerWidth * 0.78;
  let height = width / CARD_ASPECT_RATIO;

  const maxHeight = containerHeight * 0.72;
  if (height > maxHeight) {
    height = maxHeight;
    width = height * CARD_ASPECT_RATIO;
  }

  return {
    left: (containerWidth - width) / 2,
    top: (containerHeight - height) / 2,
    width,
    height,
  };
}

/** Card guide as percentage styles for an object-cover container. */
export function cardGuideToContainerStyle(layout) {
  const guide = computeCardGuideBounds(layout.containerWidth, layout.containerHeight);
  return {
    left: `${(guide.left / layout.containerWidth) * 100}%`,
    top: `${(guide.top / layout.containerHeight) * 100}%`,
    width: `${(guide.width / layout.containerWidth) * 100}%`,
    height: `${(guide.height / layout.containerHeight) * 100}%`,
  };
}

/** Map a container-space rectangle to video pixel bounds (inverse of object-cover). */
export function containerRectToVideoBounds(rect, layout) {
  const { videoWidth, videoHeight, renderedWidth, renderedHeight, offsetX, offsetY } = layout;

  const toVideoX = (containerX) => ((containerX - offsetX) / renderedWidth) * videoWidth;
  const toVideoY = (containerY) => ((containerY - offsetY) / renderedHeight) * videoHeight;

  const x1 = toVideoX(rect.left);
  const y1 = toVideoY(rect.top);
  const x2 = toVideoX(rect.left + rect.width);
  const y2 = toVideoY(rect.top + rect.height);

  const x = Math.max(0, Math.min(x1, x2));
  const y = Math.max(0, Math.min(y1, y2));
  const width = Math.min(videoWidth - x, Math.abs(x2 - x1));
  const height = Math.min(videoHeight - y, Math.abs(y2 - y1));

  return { x, y, width, height };
}

/** Centered card guide converted to video pixel bounds. */
export function layoutGuideToVideoBounds(layout) {
  const guide = computeCardGuideBounds(layout.containerWidth, layout.containerHeight);
  return containerRectToVideoBounds(guide, layout);
}
