import { IsInt, IsNotEmpty, IsPositive } from 'class-validator';
import { getConnectionManager } from 'typeorm';
import { PermissionNeedsPrincipalError } from '../../../errors/PermissionErrors';
import { PrincipalNotFoundError } from '../../../errors/PrincipalErrors';
import { Permission } from '../../entities/Permission';
import { Principal } from '../../entities/Principal';
import { PermissionAction } from '../../enums/PermissionAction';
import { PermissionTarget } from '../../enums/PermissionTargets';

/**
 * This class is used to update a Permission entity (via put request).
 */
export class UpdatePermission {

    /**
     * The updated permission'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 permissions's principal's id.
     */
    @IsInt()
    @IsPositive()
    principal: number;

    /**
     * The permissions's target.
     */
    @IsNotEmpty()
    target: PermissionTarget;

    /**
     * The permissions's action.
     */
    @IsNotEmpty()
    action: PermissionAction;

    /**
     * Updates a provided Permission entity based on this.
     */
    public async update(permission: Permission): Promise<Permission> {
        permission.principal = await this.getPrincipal();
        permission.target = this.target;
        permission.action = this.action;

        return permission;
    }

    /**
     * Loads the updated permission's principal based on it's id.
     */
    public async getPrincipal(): Promise<Principal> {
        if (this.principal === undefined || this.principal === null) {
            throw new PermissionNeedsPrincipalError();
        }
        let principal = await getConnectionManager().get().getRepository(Principal).findOne({ id: this.principal });
        if (!principal) { throw new PrincipalNotFoundError(); }
        return principal;
    }
}