import * as $int from "../gleam_stdlib/gleam/int.mjs";
import * as $paint from "../paint/paint.mjs";
import * as $canvas from "../paint/paint/canvas.mjs";
import { CustomType as $CustomType } from "./gleam.mjs";
import * as $math from "./math/math.mjs";
import * as $physics from "./physics.mjs";
import { RigidBody, Vec2, add_vec2 } from "./physics.mjs";

export class Colorable extends $CustomType {
  constructor(color) {
    super();
    this.color = color;
  }
}
export const Colorable$Colorable = (color) => new Colorable(color);
export const Colorable$isColorable = (value) => value instanceof Colorable;
export const Colorable$Colorable$color = (value) => value.color;
export const Colorable$Colorable$0 = (value) => value.color;

export class Size extends $CustomType {
  constructor(width, height) {
    super();
    this.width = width;
    this.height = height;
  }
}
export const Size$Size = (width, height) => new Size(width, height);
export const Size$isSize = (value) => value instanceof Size;
export const Size$Size$width = (value) => value.width;
export const Size$Size$0 = (value) => value.width;
export const Size$Size$height = (value) => value.height;
export const Size$Size$1 = (value) => value.height;

export class Square extends $CustomType {
  constructor(colorable, size) {
    super();
    this.colorable = colorable;
    this.size = size;
  }
}
export const Paintable$Square = (colorable, size) =>
  new Square(colorable, size);
export const Paintable$isSquare = (value) => value instanceof Square;
export const Paintable$Square$colorable = (value) => value.colorable;
export const Paintable$Square$0 = (value) => value.colorable;
export const Paintable$Square$size = (value) => value.size;
export const Paintable$Square$1 = (value) => value.size;

export class Sprite extends $CustomType {
  constructor(image, size) {
    super();
    this.image = image;
    this.size = size;
  }
}
export const Paintable$Sprite = (image, size) => new Sprite(image, size);
export const Paintable$isSprite = (value) => value instanceof Sprite;
export const Paintable$Sprite$image = (value) => value.image;
export const Paintable$Sprite$0 = (value) => value.image;
export const Paintable$Sprite$size = (value) => value.size;
export const Paintable$Sprite$1 = (value) => value.size;

export class Lucy extends $CustomType {}
export const TargetKind$Lucy = () => new Lucy();
export const TargetKind$isLucy = (value) => value instanceof Lucy;

export class Diamond extends $CustomType {
  constructor(points_value) {
    super();
    this.points_value = points_value;
  }
}
export const TargetKind$Diamond = (points_value) => new Diamond(points_value);
export const TargetKind$isDiamond = (value) => value instanceof Diamond;
export const TargetKind$Diamond$points_value = (value) => value.points_value;
export const TargetKind$Diamond$0 = (value) => value.points_value;

export class Rocket extends $CustomType {}
export const TargetKind$Rocket = () => new Rocket();
export const TargetKind$isRocket = (value) => value instanceof Rocket;

export class Target extends $CustomType {
  constructor(position, rigid_body, paintable, kind) {
    super();
    this.position = position;
    this.rigid_body = rigid_body;
    this.paintable = paintable;
    this.kind = kind;
  }
}
export const Target$Target = (position, rigid_body, paintable, kind) =>
  new Target(position, rigid_body, paintable, kind);
export const Target$isTarget = (value) => value instanceof Target;
export const Target$Target$position = (value) => value.position;
export const Target$Target$0 = (value) => value.position;
export const Target$Target$rigid_body = (value) => value.rigid_body;
export const Target$Target$1 = (value) => value.rigid_body;
export const Target$Target$paintable = (value) => value.paintable;
export const Target$Target$2 = (value) => value.paintable;
export const Target$Target$kind = (value) => value.kind;
export const Target$Target$3 = (value) => value.kind;

export function create_target() {
  let vx = ($math.random() * 6.0) - 3.0;
  let vy = ($math.random() * -4.0) - 8.0;
  let rotation_vel = ($math.random() * 2.0) - 1.0;
  let start_x = ($math.random() * 600.0) + 200.0;
  let random_type = $math.random();
  let _block;
  let r = random_type;
  if (r < 0.7) {
    _block = ["../res/lucy.svg", new Lucy()];
  } else {
    let r$1 = random_type;
    if (r$1 < 0.85) {
      _block = ["../res/diamond.svg", new Diamond(3)];
    } else {
      _block = ["../res/rocket.svg", new Rocket()];
    }
  }
  let $ = _block;
  let sprite_path;
  let target_kind;
  sprite_path = $[0];
  target_kind = $[1];
  return new Target(
    new Vec2(start_x, 900.0),
    new RigidBody(new Vec2(vx, vy), new Vec2(0.0, 0.0), 0.0, rotation_vel),
    new Sprite($canvas.image_from_src(sprite_path), new Size(120, 120)),
    target_kind,
  );
}

export function update_target(target, gravity) {
  let $ = target.rigid_body;
  let velocity;
  let acceleration;
  let rotation;
  let rotation_velocity;
  velocity = $.velocity;
  acceleration = $.acceleration;
  rotation = $.rotation;
  rotation_velocity = $.rotation_velocity;
  let total_acceleration = add_vec2(acceleration, gravity);
  let new_velocity = add_vec2(velocity, total_acceleration);
  let new_position = add_vec2(target.position, new_velocity);
  let new_rigid_body = new RigidBody(
    new_velocity,
    acceleration,
    rotation + rotation_velocity,
    rotation_velocity,
  );
  return new Target(new_position, new_rigid_body, target.paintable, target.kind);
}

export function is_point_in_target(point, target) {
  let dx = point.x - target.position.x;
  let dy = point.y - target.position.y;
  let angle_rad = ((target.rigid_body.rotation * $math.pi())) / 180.0;
  let cos_angle = $math.cos(angle_rad);
  let sin_angle = $math.sin(angle_rad);
  let local_x = (dx * cos_angle) + (dy * sin_angle);
  let local_y = (dy * cos_angle) - (dx * sin_angle);
  let $ = target.paintable;
  if ($ instanceof Square) {
    let size = $.size;
    let half_size = size / 2.0;
    return (((local_x >= (0.0 - half_size)) && (local_x <= half_size)) && (local_y >= (0.0 - half_size))) && (local_y <= half_size);
  } else {
    let size = $.size;
    let half_width = $int.to_float(size.width) / 2.0;
    let half_height = $int.to_float(size.height) / 2.0;
    return (((local_x >= (0.0 - half_width)) && (local_x <= half_width)) && (local_y >= (0.0 - half_height))) && (local_y <= half_height);
  }
}

export function paintable_to_picture(paintable) {
  if (paintable instanceof Square) {
    let colorable = paintable.colorable;
    let size = paintable.size;
    let _pipe = $paint.square(size);
    return $paint.fill(_pipe, colorable.color);
  } else {
    let image = paintable.image;
    let size = paintable.size;
    let _pipe = $paint.image(image, size.width, size.height);
    let _pipe$1 = $paint.image_scaling_pixelated(_pipe);
    return $paint.translate_xy(
      _pipe$1,
      0.0 - ($int.to_float(size.width) / 2.0),
      0.0 - ($int.to_float(size.height) / 2.0),
    );
  }
}
