import { IsBoolean, IsInt, IsOptional, IsPositive } from 'class-validator';
import { getConnection } from 'typeorm';
import { RunnerNotFoundError } from '../../../errors/RunnerErrors';
import { TrackNotFoundError } from '../../../errors/TrackErrors';
import { Runner } from '../../entities/Runner';
import { Track } from '../../entities/Track';
import { TrackScan } from '../../entities/TrackScan';

/**
 * This class is used to update a TrackScan entity (via put request)
 */
export abstract class UpdateTrackScan {
    /**
     * The updated scan's id.
     * This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to).
     */
    @IsInt()
    id: number;

    /**
     * The updated scan's associated runner's id.
     * This is important to link ran distances to runners.
     */
    @IsInt()
    @IsPositive()
    runner: number;

    /**
     * Is the updated scan valid (for fraud reasons).
     */
    @IsBoolean()
    @IsOptional()
    valid?: boolean = true;

    /**
     * The updated scan's associated station's id.
     * This is important to link ran distances to runners.
     */
    @IsInt()
    @IsPositive()
    public track: number;

    /**
     * Update a TrackScan entity based on this.
     * @param scan The scan that shall be updated.
     */
    public async update(scan: TrackScan): Promise<TrackScan> {
        scan.valid = this.valid;
        scan.runner = await this.getRunner();
        scan.track = await this.getTrack();

        return scan;
    }

    /**
     * Gets a runner based on the runner id provided via this.runner.
     */
    public async getRunner(): Promise<Runner> {
        const runner = await getConnection().getRepository(Runner).findOne({ id: this.runner });
        if (!runner) {
            throw new RunnerNotFoundError();
        }
        return runner;
    }

    /**
     * Gets a runner based on the runner id provided via this.runner.
     */
    public async getTrack(): Promise<Track> {
        const track = await getConnection().getRepository(Track).findOne({ id: this.track });
        if (!track) {
            throw new TrackNotFoundError();
        }
        return track;
    }
}