import { Component, Input, OnInit } from '@angular/core';
import { IPermissionModel } from '@fleio-api/core/permissions/model/permission.model';
import { Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';

@Component({
  selector: 'app-permissions-selector',
  templateUrl: './permissions-selector.component.html',
  styleUrls: ['./permissions-selector.component.scss']
})
export class PermissionsSelectorComponent implements OnInit {
  @Input() permissions: {
    [category: string]: IPermissionModel[];
  } = {};
  @Input() effectivePermissions: { [key: string]: boolean };
  @Input() disabled: boolean;
  selectAllTooltip = $localize`Select all`;
  deselectAllTooltip = $localize`Deselect all`;
  activeCategory;
  originalPermissions;
  searchValue;
  public searchStr$ = new Subject<string>();

  categoryChanged(key) {
    this.activeCategory = key;
  }

  selectAll() {
    for (const permission of this.permissions[this.activeCategory]) {
      permission.granted = true;
    }
  }

  deselectAll() {
    for (const permission of this.permissions[this.activeCategory]) {
      permission.granted = false;
    }
  }

  toggleCheckbox(perm: IPermissionModel) {
    if (!this.disabled) {
      perm.granted = !perm.granted;
    }
  }

  getEffectivePermission(name: string): boolean {
    if (this.effectivePermissions && this.effectivePermissions.hasOwnProperty(name)) {
      return this.effectivePermissions[name];
    }
    return false;
  }

  triggerSearch(value) {
    this.searchStr$.next(value);
  }

  updatePermissionsFromOriginal() {
    // update granted flags for original permissions based on current state
    for (const categoryKey of Object.keys(this.permissions)) {
      const grantedTemp = {};
      for (const permission of this.permissions[categoryKey]) {
        grantedTemp[permission.name] = permission.granted;
      }
      for (const permission of this.originalPermissions[categoryKey]) {
        if (Object.keys(grantedTemp).includes(permission.name)) {
          permission.granted = grantedTemp[permission.name];
        }
      }
    }

    // clone original permissions
    for (const categoryKey of Object.keys(this.originalPermissions)) {
      this.permissions[categoryKey] = JSON.parse(JSON.stringify(this.originalPermissions[categoryKey]));
    }
  }

  search(search) {
    let searchArray = [];
    if (search.indexOf(' ') > -1) {
      searchArray = search.split(' ');
    } else {
      searchArray.push(search);
    }

    this.updatePermissionsFromOriginal();

    for (const key of Object.keys(this.permissions)) {
      let i = this.permissions[key].length;
      while (i--) {
        let matches = 0;
        for (const searchValue of searchArray) {
          if (this.permissions[key][i].name.indexOf(searchValue) > -1) {
            matches++;
          } else {
            if (this.permissions[key][i].hasOwnProperty('keywords')) {
              if (this.permissions[key][i].keywords.hasOwnProperty(searchValue)) {
                for (const keyword of this.permissions[key][i].keywords[searchValue]) {
                  if (this.permissions[key][i].name.indexOf(keyword) > -1) {
                    matches++;
                  }
                }
              }
            }
          }
        }
        if (matches < searchArray.length) {
          this.permissions[key].splice(i, 1);
        }
      }
      if (this.permissions[key].length === 0) {
        delete this.permissions[key];
      }
    }
    if (!this.permissions.hasOwnProperty(this.activeCategory)) {
      this.activeCategory = Object.keys(this.permissions)[0];
    }
  }

  constructor() {
  }

  ngOnInit(): void {
    this.searchStr$.pipe(
      debounceTime(300), // discard emitted values that take less than the specified time between output
      distinctUntilChanged() // only emit when value has changed
    ).subscribe((value: string) => {
      this.search(value);
    });
    this.activeCategory = Object.keys(this.permissions)[0];
    this.originalPermissions = JSON.parse(JSON.stringify(this.permissions));
  }
}
