import { Component, ElementRef, Inject, OnInit, ViewChild } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { UsersProfilesService } from '../../../services/users-profiles.service';
import { EncService } from '../../../services/enc.service';
import { FunctionsService } from '../../../services/functions.service';
import { GdelService } from '../../../services/gdel.service';
import { UsersResponse } from '../../../interfaces/users.interface';
import { lastValueFrom } from 'rxjs';

interface SharedWithUser{
  ID: string;
  ICON: string;
  NAME: string;
  EMAIL: string;
  COLOR: string;
  SHARED: boolean;
  SHOW: boolean;
  OWNER: boolean;
}
interface FileAccess{
  error: false;
  msg: string;
  response: FileAccessInfo;
}
interface FileAccessInfo{
  access: string[];
  owner: string;
}
@Component({
    selector: 'app-share-file',
    templateUrl: './share-file.component.html',
    styleUrl: './share-file.component.css',
    standalone: false
})
export class ShareFileComponent implements OnInit {
  file: string;
  isLoading: boolean;
  hasError: boolean;
  errorStr: string;

  sharedUsers: SharedWithUser[];

  avatarColors = {
    A: 244, B: 67, C:  54, D: 233, E: 30, F:  99, G: 156, H:  39, I: 176, 
    J: 103, K: 58, L:  58, M: 183, N: 63, Ñ:  81, O: 181, P:  33, Q: 150, 
    R: 243, S:  3, T: 169, U: 244, V: 76, W: 175, X:  80, Y: 255, Z: 193
  };

  @ViewChild('filter') filter?: ElementRef;

  constructor(
    @Inject(MAT_DIALOG_DATA) private _data: any,
    private _usersProfService: UsersProfilesService,
    private _encService: EncService,
    private _funcService: FunctionsService,
    private _gdelService: GdelService,
    private _dialogRef: MatDialogRef<ShareFileComponent>
  ) {
    this.file = "";
    this.isLoading = true;
    this.hasError = false;
    this.errorStr = '';
    this.sharedUsers = [];
  }

  ngOnInit(): void {
    this.file = this._data.idFile;
    this.getUsers();
  }

  async getUsers(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let users: UsersResponse = await lastValueFrom(this._usersProfService.getUsers(idUser, 1));
      
      this.hasError = users.error;
      this.errorStr = users.msg;

      if(!this.hasError){
        for(const user of users.response){
          let idDec = await this._encService.decrypt(user.IDUSUARIO);
          let userName = `${this._funcService.buildName(user.NOMBRE, user.APEPAT, user.APEMAT)} (${idDec})`;
          let userColor = "rgb(";

          for(let i = 0; i < 3; i++){
            let char = userName.charAt(i) as never;
            let colorNum = this.avatarColors[char];

            userColor += `${colorNum}, `;
          }

          userColor = userColor.substring(0, userColor.length - 2);
          userColor += ")";

          let nameArr = userName.split(' ');
          let iconStr = `${nameArr[0][0]}${nameArr[1][0]}`;

          let sharedUser: SharedWithUser = {
            ID: user.IDUSUARIO,
            ICON: iconStr,
            NAME: userName,
            EMAIL: user.EMAIL,
            COLOR: userColor,
            SHARED: false,
            SHOW: true,
            OWNER: false
          };

          this.sharedUsers.push(sharedUser);
        }
        
        this.getFileAccess();
      }else{
        this.isLoading = false;
      }
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado (1).';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado (2).';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
    }
  }

  async getFileAccess(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let idFileEnc = await this._encService.encrypt(this.file);

      let fileAccess: FileAccess = await lastValueFrom(this._gdelService.getFileAccess(
        idFileEnc,
        idUser,
        1
      ));

      this.hasError = fileAccess.error;
      this.errorStr = fileAccess.msg;

      if(!this.hasError){
        let ownerDec = await this._encService.decrypt(fileAccess.response.owner);
        let usersAux: SharedWithUser[] = [];

        for(const user of this.sharedUsers){
          let userID = await this._encService.decrypt(user.ID);
          if(userID != ownerDec){
            usersAux.push(user);
          }
        }

        let ownerObj: SharedWithUser | null = null;
        for(const user of this.sharedUsers){
          let idOwnerDec = await this._encService.decrypt(user.ID);
          if(idOwnerDec == ownerDec){
            ownerObj = user;
          }
        }
        
        if(ownerObj != null){
          ownerObj.NAME = ownerObj.NAME + ' - PROPIETARIO';
          ownerObj.OWNER = true;

          usersAux.splice(0, 0, ownerObj);
          this.sharedUsers = usersAux;

          for(const access of fileAccess.response.access){
            let idDec = await this._encService.decrypt(access);

            let accessFilt: SharedWithUser | null = null;
            for(const user of this.sharedUsers){
              let idOwnerDec = await this._encService.decrypt(user.ID);
              if(idOwnerDec == idDec){
                accessFilt = user;
              }
            }
            
            if(accessFilt != null){
              accessFilt.SHARED = true;
            }
          }
        }
      }
      
      this.isLoading = false;
    }catch(error: any){
      console.log(error);
      
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado (3).';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado (4).';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
    }
  }

  filterUsers(value: string){
    if(value != '' && value != undefined && value != null){
      let valLower = value.toLocaleLowerCase();

      let filteredUsersH = this.sharedUsers.filter(item => !item.NAME.toLocaleLowerCase().includes(valLower) && !item.EMAIL.toLocaleLowerCase().includes(valLower));
      for(const filteredUser of filteredUsersH){
        filteredUser.SHOW = false;
      }

      let filteredUsersS = this.sharedUsers.filter(item => item.NAME.toLocaleLowerCase().includes(valLower) || item.EMAIL.toLocaleLowerCase().includes(valLower));
      for(const filteredUser of filteredUsersS){
        filteredUser.SHOW = true;
      }
    }else{
      for(const filteredUser of this.sharedUsers){
        filteredUser.SHOW = true;
      }
    }
  }

  clearFilter(){
    this.filter!.nativeElement.value = '';
    this.filterUsers('');
  }

  async closeDigalog(){
    let usersWithAccess: string[] = [];
    for(const user of this.sharedUsers){
      if(user.SHARED){
        usersWithAccess.push(user.ID);
      }
    }
    
    this._dialogRef.close(JSON.stringify(usersWithAccess));
  }
}
