import { IsInt, IsOptional, IsString } from "class-validator";
import { ChildEntity, Column, OneToMany } from "typeorm";
import { ResponseRunnerOrganization } from '../responses/ResponseRunnerOrganization';
import { Address } from './Address';
import { Runner } from './Runner';
import { RunnerGroup } from "./RunnerGroup";
import type { RunnerTeam } from "./RunnerTeam";

/**
 * Defines the RunnerOrganization entity.
 * This usually is a school, club or company.
*/
@ChildEntity()
export class RunnerOrganization extends RunnerGroup {

  /**
   * The organizations's address.
   */
  @IsOptional()
  @Column(type => Address)
  address?: Address;

  /**
   * The organization's teams.
   * Used to link teams to a organization.
   */
  @OneToMany(() => require("./RunnerTeam").RunnerTeam, (team: RunnerTeam) => team.parentGroup, { nullable: true })
  teams!: RunnerTeam[];

  /**
   * The organization's api key for self-service registration.
   * The api key can be used for the /runners/register/:token endpoint.
   * Is has to be base64 encoded if used via the api (to keep url-safety).
   */
  @Column({ nullable: true, unique: true })
  @IsString()
  @IsOptional()
  key?: string;

  /**
   * Returns all runners associated with this organization (directly or indirectly via teams).
   */
  public get allRunners(): Runner[] {
    let returnRunners: Runner[] = new Array<Runner>();
    returnRunners.push(...this.runners);
    for (let team of this.teams) {
      returnRunners.push(...team.runners)
    }
    return returnRunners;
  }

  /**
   * Returns the total distance ran by this group's runners based on all their valid scans.
  */
  @IsInt()
  public get distance(): number {
    return this.allRunners.reduce((sum, current) => sum + current.distance, 0);
  }

  /**
   * Returns the total donations a runner has collected based on his linked donations and distance ran.
  */
  @IsInt()
  public get distanceDonationAmount(): number {
    return this.allRunners.reduce((sum, current) => sum + current.distanceDonationAmount, 0);
  }

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