import {
  IsInt,
  IsNotEmpty,

  IsNumber,

  IsPositive
} from "class-validator";
import { ChildEntity, Column, Index, ManyToOne } from "typeorm";
import { ResponseTrackScan } from '../responses/ResponseTrackScan';
import type { RunnerCard } from "./RunnerCard";
import { Scan } from "./Scan";
import type { ScanStation } from "./ScanStation";
import type { Track } from "./Track";

/**
 * Defines the TrackScan entity.
 * A track scan usaually get's generated by a scan station.
 */
@ChildEntity()
@Index(['track'])
@Index(['card'])
@Index(['station'])
@Index(['timestamp'])
@Index(['station', 'timestamp'])
export class TrackScan extends Scan {
  /**
   * The scan's associated track.
   * This is used to determine the scan's distance.
   */
  @IsNotEmpty()
  @ManyToOne(() => require("./Track").Track, (track: Track) => track.scans, { nullable: true })
  track!: Track;

  /**
   * The runnerCard associated with the scan.
   * This get's saved for documentation and management purposes.
   */
  @IsNotEmpty()
  @ManyToOne(() => require("./RunnerCard").RunnerCard, (card: RunnerCard) => card.scans, { nullable: true })
  card!: RunnerCard;

  /**
   * The scanning station that created the scan.
   * Mainly used for logging and traceing back scans (or errors)
   */
  @IsNotEmpty()
  @ManyToOne(() => require("./ScanStation").ScanStation, (station: ScanStation) => station.scans, { nullable: true })
  station!: ScanStation;

  /**
   * The scan's distance in meters.
   * This just get's loaded from it's track.
   */
  @IsInt()
  @IsPositive()
  public get distance(): number {
    return this.track.distance;
  }

  /**
   * The scan's creation timestamp.
   * Will be used to implement fraud detection.
   */
  @Column()
  @IsInt()
  timestamp: number;

  /**
   * The scan's lap time.
   * This simply get's calculated from the last lap time;
   */
  @Column()
  @IsNumber()
  lapTime: number;

  /**
   * Turns this entity into it's response class.
   */
  public toResponse(): ResponseTrackScan {
    return new ResponseTrackScan(this);
  }
}
