import DashLineShader from "./rendering/shaders/graphics/dash-line.mjs";

/**
 * The dash line thickness.
 * @type {number}
 */
let dashLineThickness;

/**
 * The inner dash line shader.
 * @type {DashLineShader}
 */
let innerDashLineShader;

/**
 * The outer dash line shader.
 * @type {DashLineShader}
 */
let outerDashLineShader;

/**
 * Draw a border.
 * @param {PIXI.smooth.SmoothGraphics} graphics  The graphics to draw the shape into.
 * @param {PIXI.Rectangle|PIXI.RoundedRectangle|PIXI.Circle|PIXI.Ellipse|PIXI.Polygon
 *   |(graphics: PIXI.smooth.SmoothGraphics) => void} shape  The shape to draw or a draw callback.
 * @param {object} [options]                  Additional options.
 * @param {PIXI.ColorSource} [options.color]  The border color. Default: `0xFFFFFF`.
 * @param {boolean} [options.dashed]          Dashed border? Default: `false`.
 * @param {number} [options.alignment]        The alignment of the outline. Default: `0.5`.
 * @param {boolean} [options.clear]           Clear the graphics before drawing the border? Default: `0.5`.
 */
export function drawBorder(graphics, shape, {color=0xFFFFFF, dashed=false, alignment=0.5, clear=true}={}) {
  const thickness = CONFIG.Canvas.objectBorderThickness * canvas.dimensions.uiScale;
  if ( dashLineThickness !== thickness ) innerDashLineShader = outerDashLineShader = undefined;
  const lineWidth = thickness / 2;
  const outlineThickness = thickness / 4;
  const outerLineStyle = {width: lineWidth + (2 * outlineThickness), color: 0x000000, join: PIXI.LINE_JOIN.ROUND,
    alignment: ((alignment - 0.5) * 0.5) + 0.5};
  const innerLineStyle = {width: lineWidth, color, join: PIXI.LINE_JOIN.ROUND, alignment};
  if ( dashed ) {
    const innerDash = thickness * 2;
    const innerGap = innerDash * (5 / 8);
    const innerOffset = innerGap;
    innerLineStyle.shader = innerDashLineShader ??= new DashLineShader(
      {dash: innerDash, gap: innerGap, offset: innerOffset});
    const outerDash = innerDash + (2 * outlineThickness);
    const outerGap = Math.max(innerGap - (2 * outlineThickness), 0);
    const outerOffset = innerGap - outlineThickness;
    outerLineStyle.shader = outerDashLineShader ??= new DashLineShader(
      {dash: outerDash, gap: outerGap, offset: outerOffset});
  }
  if ( clear ) graphics.clear();
  let drawShape;
  if ( [PIXI.Rectangle, PIXI.RoundedRectangle, PIXI.Circle, PIXI.Ellipse, PIXI.Polygon].some(
    shapeClass => shape instanceof shapeClass) ) {
    drawShape = g => g.drawShape(shape);
  }
  else drawShape = shape;
  graphics.lineStyle(outerLineStyle);
  drawShape(graphics);
  graphics.lineStyle(innerLineStyle);
  drawShape(graphics);
}
