/* Copyright CloudLinux Zug GmbH 2010-2017 All Rights Reserved
 *
 * Licensed under CLOUD LINUX LICENSE AGREEMENT
 * http://cloudlinux.com/docs/LICENSE.TXT
 */

import { Component, OnInit, ViewChild } from '@angular/core';
import { UsersGrid } from './utils/users_grid';
import { Column } from './utils/column';
import { XHR } from './utils/xhr';
import { User } from './model/user';
import { UsersRepo } from './repository/users_repo';
import { BaseComponent } from './utils/base_component';
import { AppState } from './app.service';
import { US_RESELLER, ViewModes } from './services/view_modes';
import { Access } from './services/access';
import { TranslateService } from '@ngx-translate/core';
import { isObject } from 'rxjs/util/isObject';
import { LoaderSelector } from './utils/loader';


declare var mainAction: any;

interface UserColumnInfo {
    column: Column;
    limitName: string;
}

@Component({
  selector: '.users_block',
  template: require('./../templates/users.component.html'),
  styles: [
    require('../styles/users.component.less')
  ],
  providers: [XHR, UsersRepo, ViewModes, Access, TranslateService],
})

export class UsersComponent extends BaseComponent{
    static columnInfoArray: Array<UserColumnInfo> = [
        {
            column: new Column({
                name: 'limits_cpu_all', descr: 'SPEED', convertToFormat: 'number'
            }),
            limitName: 'cpu'
        },
        {
            column: new Column({
                name: 'limits_vmem', descr: 'VMEM',
                convertToFormat: 'byte-amount', showEditOrValue: true, hidden: true
            }),
            limitName: 'vmem'
        },
        {
            column: new Column({
                name: 'limits_pmem', descr: 'PMEM', convertToFormat: 'byte-amount'
            }),
            limitName: 'pmem'
        },
        {
            column: new Column({
                name: 'limits_io_all', descr: 'IO', convertToFormat: 'byte-amount'
            }),
            limitName: 'io'
        },
        {
            column: new Column({
                name: 'limits_iops', descr: 'IOPS', convertToFormat: 'number'
            }),
            limitName: 'iops'
        },
        {
            column: new Column({
                name: 'limits_ep', descr: 'EP', convertToFormat: 'number'
            }),
            limitName: 'ep'
        },
        {
            column: new Column({
                name: 'limits_nproc', descr: 'NPROC', convertToFormat: 'number'
            }),
            limitName: 'nproc'
        },
        {
            column: new Column({
                name: 'limits_inodes_hard', descr: 'INODES', convertToFormat: 'number'
            }),
            limitName: 'inodes'
        },
    ];
    originalUsers: Array<User>;
    users: Array<User>;
    columns: Array<Column> = [];
    availableLimits: Array<string>;
    globalCageFsStatus: boolean;
    globalMySqlGov: boolean;

  @ViewChild(UsersGrid) UsersGrid: UsersGrid;

  // Filter options
  private _filterField: string;
  set filterField(value: string) {
    this._filterField = value;
    if (typeof this.originalUsers !== 'undefined') {
      this.doFilter();
    }
  }
  get filterField(): string {
    return this._filterField;
  }

  private _mysqlIgnore = false;
  set mysqlIgnore(value: boolean) {
    this._mysqlIgnore = value;
    this.doFilter();
  }
  get mysqlIgnore(): boolean {
    return this._mysqlIgnore;
  }

  private _cagefsEnabled = false;
  set cagefsEnabled(value: boolean) {
    this._cagefsEnabled = value;
    this.doFilter();
  }
  get cagefsEnabled(): boolean {
    return this._cagefsEnabled;
  }

  public rowsOnPage: number = 25;

  constructor(
      private usersRepo: UsersRepo,
      public appState: AppState,
      private viewModeService: ViewModes,
      private accessService: Access
  ) {
    super();
    this.loaderSelector = new LoaderSelector('.users_block');
    this.load();
  }

  public updateUsers($event) {
      if (isObject($event) && $event.response) {
          this.updateResponseUsers($event.response);
      } else {
          this.loading = true;
          this.load();
      }

  }

  load(){
    this.usersRepo.getAllUsers()
        .then((data: any) => {
          if (this.appState.get('isAdmin')) {
            this.viewModeService.concatResellerWithUser(data);
            this.viewModeService.detectUserTypes(data, this.viewModes);
          }
          for (let user of data.users) {
            this.accessService.dropPermission(data, user);
          }
          this.originalUsers = this.parseUsers(data);
          this.doFilter();
          this.columns = this.getColumns(data);
          this.UsersGrid.key = this.columns[1].name;
          this.UsersGrid.noFoundText = 'NO USERS FOUND';
          this.globalCageFsStatus = (data.cageFS === 'enabled');
          this.globalMySqlGov = (data.mySqlGov === 'enabled');
          this.loading = false;
        })
        .catch((data: any) => {
          this.loading = false;
        });
  }

  parseUsers(response) {
      return response.users.map((user, i) => {
          return new User(
              response, i, this.appState, this.usersRepo
          );
      });
  }

  getColumns(data): Array<Column> {
    if (!data.users.length) {
      return [];
    }

    this.availableLimits = data.users[0].limits;
    let columns =  [
        new Column({name: 'plus', descr: '', convertToFormat: 'string'}).sortableDisable(),
        new Column({name: 'id', descr: 'LVE ID', convertToFormat: 'number'}),
        new Column({name: 'username', descr: 'Username', convertToFormat: 'string'}),
        new Column({name: 'domain', descr: 'Domain', convertToFormat: 'string'})
    ];

    for (let columnInfo of UsersComponent.columnInfoArray){
        if (this.availableLimits.hasOwnProperty(columnInfo.limitName))
            columns.push(columnInfo.column);
    }

    columns.push(new Column({name: 'package', descr: 'Package', convertToFormat: 'string'}));
    columns.push(new Column({name: 'actions', descr: 'Actions', convertToFormat: 'string'})
        .sortableDisable());
    return columns;
  }

  public doFilter: Function = () => {
    let rows: Array<User>;
    if (this.appState.get('isAdmin')) {
      rows = this.viewModeService.switchViewMode(
          this.availableViewModes,
          this.originalUsers
      );
    } else {
      rows = this.originalUsers;
    }

    this.users = rows.filter((row, index) => {
        if (this.mysqlIgnore === true){
            if (row.my_sql_gov_cpu !== 'ignored'){
                return false;
            }
        }
        if (this.cagefsEnabled === true) {
            if (row.cagefs !== 'enabled') {
                return false;
            }
        }
        if (typeof this.filterField  !== 'undefined' && this.filterField !== '') {
            return (
                row.username.includes(this.filterField)
                || (typeof row.id !== 'undefined' && row.id.toString().startsWith(this.filterField))
                || (typeof row.domain !== 'undefined' && row.domain.includes(this.filterField))
            );
        }
        return true;
    });

    this.UsersGrid.noFound = (this.users.length === 0);
  };

  toggleMysqlIgnore(){
    this.mysqlIgnore = !this.mysqlIgnore;
  }

  toggleCagefsEnabled(){
    this.cagefsEnabled = !this.cagefsEnabled;
  }

  ngAfterViewInit(){
    this.loading = true;
  }

  private findUserById(userId: number) {
      return this.originalUsers.find(row => row.id === userId && !row.isReseller);
  }

    /**
     * Update reseller's end users for specified Reseller by its name.
     * @param response Server response with users data
     */
  public updateResponseUsers(response: any) {
      for (let i = 0; i < response.users.length; i++) {
          let userData = response.users[i];
          if (userData.id > 0 && userData.userType !== US_RESELLER) {
              let user = this.findUserById(userData.id);
              if (user) {
                  user.loadData(response, i);
              } else {
                  this.originalUsers.push(
                      new User(response, i, this.appState, this.usersRepo)
                  );
              }
          }
      }
      this.doFilter();
  }


}
