/**
 * Value Object: LiveryDecal
 * Represents a decal/logo placed on a livery
 */
 
import type { ValueObject } from '@core/shared/domain/ValueObject';
import { RacingDomainValidationError } from '../errors/RacingDomainError';

export type DecalType = 'sponsor' | 'user';

export interface LiveryDecalProps {
  id: string;
  imageUrl: string;
  x: number;
  y: number;
  width: number;
  height: number;
  rotation: number; // Degrees, 0-360
  zIndex: number;
  type: DecalType;
}
 
export class LiveryDecal implements ValueObject<LiveryDecalProps> {
  readonly id: string;
  readonly imageUrl: string;
  readonly x: number;
  readonly y: number;
  readonly width: number;
  readonly height: number;
  readonly rotation: number;
  readonly zIndex: number;
  readonly type: DecalType;

  private constructor(props: LiveryDecalProps) {
    this.id = props.id;
    this.imageUrl = props.imageUrl;
    this.x = props.x;
    this.y = props.y;
    this.width = props.width;
    this.height = props.height;
    this.rotation = props.rotation;
    this.zIndex = props.zIndex;
    this.type = props.type;
  }

  static create(props: Omit<LiveryDecalProps, 'rotation'> & { rotation?: number }): LiveryDecal {
    const propsWithRotation = {
      ...props,
      rotation: props.rotation ?? 0,
    };
    this.validate(propsWithRotation);
    return new LiveryDecal(propsWithRotation);
  }

  private static validate(props: LiveryDecalProps): void {
    if (!props.id || props.id.trim().length === 0) {
      throw new RacingDomainValidationError('LiveryDecal ID is required');
    }

    if (!props.imageUrl || props.imageUrl.trim().length === 0) {
      throw new RacingDomainValidationError('LiveryDecal imageUrl is required');
    }

    if (props.x < 0 || props.x > 1) {
      throw new RacingDomainValidationError('LiveryDecal x coordinate must be between 0 and 1 (normalized)');
    }

    if (props.y < 0 || props.y > 1) {
      throw new RacingDomainValidationError('LiveryDecal y coordinate must be between 0 and 1 (normalized)');
    }

    if (props.width <= 0 || props.width > 1) {
      throw new RacingDomainValidationError('LiveryDecal width must be between 0 and 1 (normalized)');
    }

    if (props.height <= 0 || props.height > 1) {
      throw new RacingDomainValidationError('LiveryDecal height must be between 0 and 1 (normalized)');
    }

    if (!Number.isInteger(props.zIndex) || props.zIndex < 0) {
      throw new RacingDomainValidationError('LiveryDecal zIndex must be a non-negative integer');
    }

    if (props.rotation < 0 || props.rotation > 360) {
      throw new RacingDomainValidationError('LiveryDecal rotation must be between 0 and 360 degrees');
    }

    if (!props.type) {
      throw new RacingDomainValidationError('LiveryDecal type is required');
    }
  }

  /**
   * Move decal to new position
   */
  moveTo(x: number, y: number): LiveryDecal {
    return LiveryDecal.create({
      ...this,
      x,
      y,
    });
  }

  /**
   * Resize decal
   */
  resize(width: number, height: number): LiveryDecal {
    return LiveryDecal.create({
      ...this,
      width,
      height,
    });
  }

  /**
   * Change z-index
   */
  setZIndex(zIndex: number): LiveryDecal {
    return LiveryDecal.create({
      ...this,
      zIndex,
    });
  }

  /**
    * Rotate decal
    */
   rotate(rotation: number): LiveryDecal {
     // Normalize rotation to 0-360 range
     const normalizedRotation = ((rotation % 360) + 360) % 360;
     return LiveryDecal.create({
       ...this,
       rotation: normalizedRotation,
     });
   }

   get props(): LiveryDecalProps {
    return {
      id: this.id,
      imageUrl: this.imageUrl,
      x: this.x,
      y: this.y,
      width: this.width,
      height: this.height,
      rotation: this.rotation,
      zIndex: this.zIndex,
      type: this.type,
    };
  }

  /**
   * Check if this decal overlaps with another
   */
  overlapsWith(other: LiveryDecal): boolean {
    const thisRight = this.x + this.width;
    const thisBottom = this.y + this.height;
    const otherRight = other.x + other.width;
    const otherBottom = other.y + other.height;
 
    return !(
      thisRight <= other.x ||
      this.x >= otherRight ||
      thisBottom <= other.y ||
      this.y >= otherBottom
    );
  }

  equals(other: ValueObject<LiveryDecalProps>): boolean {
    const a = this.props;
    const b = other.props;
    return (
      a.id === b.id &&
      a.imageUrl === b.imageUrl &&
      a.x === b.x &&
      a.y === b.y &&
      a.width === b.width &&
      a.height === b.height &&
      a.rotation === b.rotation &&
      a.zIndex === b.zIndex &&
      a.type === b.type
    );
  }
}