export class Permissions {
  static readonly Admin = new Permissions(2 << 0);
  static readonly Users = new Permissions(2 << 1);
  static readonly Reports = new Permissions(2 << 2);
  static readonly Feedback = new Permissions(2 << 3);
  static readonly Settings = new Permissions(2 << 4);
  static readonly Tools = new Permissions(2 << 5);

  readonly value: number;

  constructor(value: number | number[] | Permissions[] | null) {
    if (value == null) {
      this.value = 0;
    } else if (typeof value == 'number') {
      this.value = value;
    } else if (Array.isArray(value)) {
      let finalValue = 0;
      for (const v of value) {
        if (typeof v == 'number') {
          finalValue |= v;
        } else {
          finalValue |= v.value;
        }
      }
      this.value = finalValue;
    } else {
      throw 'Invalid arguments';
    }
  }

  toJSON() {
    return this.value;
  }

  static asOptions() {
    return {
      [Permissions.Admin.value]: 'Admin',
      [Permissions.Users.value]: 'Users',
      [Permissions.Reports.value]: 'Reports',
      [Permissions.Feedback.value]: 'Feedback',
      [Permissions.Settings.value]: 'Settings',
      [Permissions.Tools.value]: 'Tools'
    };
  }

  get admin() {
    return (this.value & Permissions.Admin.value) != 0;
  }
  get users() {
    return (this.value & Permissions.Users.value) != 0;
  }
  get reports() {
    return (this.value & Permissions.Reports.value) != 0;
  }
  get feedback() {
    return (this.value & Permissions.Feedback.value) != 0;
  }
  get settings() {
    return (this.value & Permissions.Settings.value) != 0;
  }
  get tools() {
    return (this.value & Permissions.Tools.value) != 0;
  }

  hasPermissions(other: Permissions) {
    return (other.value & this.value) == other.value;
  }

  static allPermissions() {
    return [
      Permissions.Admin,
      Permissions.Users,
      Permissions.Reports,
      Permissions.Feedback,
      Permissions.Settings,
      Permissions.Tools
    ];
  }
}
