import {
  IsEnum,
  IsInt,
  IsNotEmpty,
  IsPositive
} from "class-validator";
import { BeforeInsert, BeforeUpdate, Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
import { PermissionAction } from '../enums/PermissionAction';
import { PermissionTarget } from '../enums/PermissionTargets';
import { ResponsePermission } from '../responses/ResponsePermission';
import type { Principal } from './Principal';
/**
 * Defines the Permission entity.
 * Permissions can be granted to principals.
 * The permissions possible targets and actions are defined in enums.
*/
@Entity()
export class Permission {
  /**
   * Autogenerated unique id (primary key).
   */
  @PrimaryGeneratedColumn()
  @IsInt()
  id: number;

  /**
   * The permission's principal.
   */
  @ManyToOne(() => require("./Principal").Principal, (principal: Principal) => principal.permissions)
  principal!: Principal;

  /**
   * The permission's target.
   * This get's stored as the enum value's string representation for compatability reasons.
   */
  @Column({ type: 'varchar' })
  @IsNotEmpty()
  @IsEnum(PermissionTarget)
  target: PermissionTarget;

  /**
   * The permission's action.
   * This get's stored as the enum value's string representation for compatability reasons.
   */
  @Column({ type: 'varchar' })
  @IsEnum(PermissionAction)
  action: PermissionAction;

  @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);
  }

  /**
   * Turn this into a string for exporting and jwts.
   * Mainly used to shrink the size of jwts (otherwise the would contain entire objects).
   */
  public toString(): string {
    return this.target + ":" + this.action;
  }

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