import {
  IsInt,
  IsNotEmpty,
  IsOptional,
  IsPositive,
  IsString
} from "class-validator";
import { BeforeInsert, BeforeUpdate, Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { ResponseTrack } from '../responses/ResponseTrack';
import type { ScanStation } from "./ScanStation";
import type { TrackScan } from "./TrackScan";

/**
 * Defines the Track entity.
*/
@Entity()
export class Track {
  /**
   * Autogenerated unique id (primary key).
   */
  @PrimaryGeneratedColumn()
  @IsInt()
  id: number;

  /**
   * The track's name.
   * Mainly here for UX.
   */
  @Column()
  @IsString()
  @IsNotEmpty()
  name: string;

  /**
   * The track's length/distance in meters.
   * Will be used to calculate runner's ran distances.
   */
  @Column()
  @IsInt()
  @IsPositive()
  distance: number;

  /**
   * The minimum time a runner should take to run a lap on this track (in seconds).
   * Will be used for fraud detection.
   */
  @Column({ nullable: true })
  @IsInt()
  @IsOptional()
  minimumLapTime?: number;

  /**
   * Used to link scan stations to a certain track.
   * This makes the configuration of the scan stations easier.
   */
  @OneToMany(() => require("./ScanStation").ScanStation, (station: ScanStation) => station.track, { nullable: true })
  stations!: ScanStation[];

  /**
   * Used to link track scans to a track.
   * The scan will derive it's distance from the track's distance.
   */
  @OneToMany(() => require("./TrackScan").TrackScan, (scan: TrackScan) => scan.track, { nullable: true })
  scans!: TrackScan[];

  @Column({ type: 'bigint', nullable: true, readonly: true })
  @IsInt()
  @IsPositive()
  created_at: number;

  @Column({ type: 'bigint', nullable: true })
  @IsInt()
  @IsPositive()
  updated_at: number;

  @BeforeInsert()
  public setCreatedAt() {
    this.created_at = Math.floor(Date.now() / 1000);
    this.updated_at = Math.floor(Date.now() / 1000);
  }

  @BeforeUpdate()
  public setUpdatedAt() {
    this.updated_at = Math.floor(Date.now() / 1000);
  }

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