import { marker } from '@biesbjerg/ngx-translate-extract-marker';
import { MemberPermissions } from '../../crypto/group_config/chain-flag-parser';
import { AccountAvatarRecord } from './account-records';
import { DecryptionState, ID } from './common-records';
import { ResourceType } from './sidebar-records';
declare var twemoji;

export type ReactionEnum = number;

export interface RoomData extends DecryptionState {
  name?: string;
  avatar?: ArrayBuffer;
  /**
   * In some case you need to cache the data, so later you can dercypt it with
   * a newly got pinnedKey
   * So if your room is unavilable, you should remember the data
   */
  rawData?: Uint8Array;
}

export interface RoomRecord {
  id: ID;
  ignore?: boolean | null;
  nanoSessions: { [key: string]: number };
  ownerAccountId: ID;
  pinnedKey?: Uint8Array;
  savedKey?: Uint8Array;
  seenMessageId?: ID; // first time, or if you are anonym, not member it can be optionally
  topMessageId: ID;
  inaccessible?: boolean;
}

export interface RawRoomWithData extends RoomRecord {
  data: Uint8Array;
}

export interface RoomWithData extends RoomRecord {
  data: RoomData;
}

export interface RoomDetail {
  id: ID;
  ownerAccountId: ID;
  peerSeenIds?: { [id: ID]: ID }; // user: message
  pinnedMessageIds: ID[];
  type: ResourceType.ROOM;
}

export interface DialogueDetail {
  id: ID;
  peerSeenId: ID | null; // user
  pinnedMessageIds: ID[];
  type: ResourceType.DIALOGUE;
}

export interface DialogueRecord {
  hidden: boolean | null;
  ignore: boolean | null;
  id: ID;
  seenMessageId: ID | null;
  topMessageId: ID | null;
}

export interface MessageRecord {
  id;
  posterId;
  content: string;
  edited: boolean;
  error?: boolean;
  errorMessage?: string;
  reactions: { [userId: ID]: ReactionEnum };
}

export interface roomConfigRecord {
  block: Uint8Array;
  id: string;
  signature: Uint8Array;
}

export interface RoomMemberRecord {
  accounts: RoomMemberAccountRecord[];
  id: string;
  ownerAccountId: string;
}

export interface RoomMemberAccountRecord {
  administrator: boolean;
  id: string;
  msgBrdModerate: null | boolean;
}

export interface RoomPermissionRecord {
  accounts: RoomPermissionAccountRecord[];
  maxMembers: number;
  id: string;
  msgBrdReadOnly: null | boolean;
  noReactions: null | boolean;
  ownerAccountId: string;
}

export interface RoomPermissionAccountRecord {
  id: string;
  rejected: null | boolean;
  msgBrdModerate: null | boolean;
}

export interface RoomMyPermissionAccountRecord {
  driveAdhoc: boolean;
  driveWrite: boolean;
  administrator: boolean;
  id: string;
  msgBrdModerate: null | boolean;
  driveUpload: boolean;
}

export interface RoomMyPermissionRecord {
  account?: RoomMyPermissionAccountRecord;
  allowAnonymous: boolean;
  id: string;
  msgBrdReadOnly?: null | boolean; // TODO def
  ownerAccountId?: string;
  noReactions?: null | boolean;
}

export const ERROR_NOT_AVAILABLE = marker('Not Available');
export const ERROR_DATASET_ERROR = marker('Dataset Error');
export const ERROR_DECRYPTION_ERROR = marker('Decryption Error');

export enum PermissionRole {
  ADMIN = 'admin',
  MODERATOR = 'moderator',
  MEMBER = 'member',
}

export enum PermissionDriveAccess {
  FULL_ACCESS = 'full_access',
  UPLOAD_ONLY = 'upload_only',
  READ_ONLY = 'read_only',
}
export class RoomMember {
  public user: AccountAvatarRecord;
  public permissions: MemberPermissions;
  public newMember: boolean;
  public newPermissions: MemberPermissions;

  constructor(
    user: AccountAvatarRecord,
    permissions: MemberPermissions,
    newMember: boolean = true
  ) {
    this.user = user;

    if (newMember) {
      // the "old" values set to false
      this.permissions = <any>{};
      for (let key in permissions) {
        this.permissions[key] = false;
      }
    } else {
      this.permissions = Object.assign({}, permissions);
    }

    this.newPermissions = Object.assign({}, permissions);
  }

  public get hasChanged(): boolean {
    if (this.newMember) return true;
    for (let key in this.permissions) {
      if (this.permissions[key] != this.newPermissions[key]) {
        return true;
      }
    }
    return false;
  }
}

let assetFolder = 'assets/img/twemoji/72x72/';
let assetExt = '.png';

// ❤️🎉🏆👀👌👍👎👏💔💯🔥😁😇😈😍😎😐😢😨😭😱😴🙏🤔🤝🤣🤨🤩🤬🤮🤯🥰🥱🥴💪😂😉😊🙃😆😠😮
export let reactionList: { index: ReactionEnum; emoji: string; src?: string }[] = [
  { index: 1, emoji: '❤️' },
  { index: 2, emoji: '🎉' },
  { index: 3, emoji: '🏆' },
  { index: 4, emoji: '👀' },
  { index: 5, emoji: '👌' },
  { index: 6, emoji: '👍' },
  { index: 7, emoji: '👎' },
  { index: 8, emoji: '👏' },
  { index: 9, emoji: '💔' },
  { index: 10, emoji: '💯' },
  { index: 11, emoji: '🔥' },
  { index: 12, emoji: '😁' },
  { index: 13, emoji: '😇' },
  { index: 14, emoji: '😈' },
  { index: 15, emoji: '😍' },
  { index: 16, emoji: '😎' },
  { index: 17, emoji: '😐' },
  { index: 18, emoji: '😢' },
  { index: 19, emoji: '😨' },
  { index: 20, emoji: '😭' },
  { index: 21, emoji: '😱' },
  { index: 22, emoji: '😴' },
  { index: 23, emoji: '🙏' },
  { index: 24, emoji: '🤔' },
  { index: 25, emoji: '🤝' },
  { index: 26, emoji: '🤣' },
  { index: 27, emoji: '🤨' },
  { index: 28, emoji: '🤩' },
  { index: 29, emoji: '🤬' },
  { index: 30, emoji: '🤮' },
  { index: 31, emoji: '🤯' },
  { index: 32, emoji: '🥰' },
  { index: 33, emoji: '🥱' },
  { index: 34, emoji: '🥴' },
  { index: 35, emoji: '💪' },
  { index: 36, emoji: '😂' },
  { index: 37, emoji: '😉' },
  { index: 38, emoji: '😊' },
  { index: 39, emoji: '🙃' },
  { index: 40, emoji: '😆' },
  { index: 41, emoji: '😠' },
  { index: 42, emoji: '😮' },
];

export let reactionIndexSrcMap: { [index: string]: string } = {};

reactionList.forEach((r) => {
  twemoji.parse(r.emoji, {
    callback: (icon, options) => {
      let src = assetFolder + (icon ? icon : '1f532') + assetExt;
      r.src = src;
      reactionIndexSrcMap[r.index] = src;
    },
  });
});
