/*
 * Copyright (C) 2018 Robert Bosch GmbH Copyright (C) 2018 Robert Bosch Manufacturing Solutions GmbH, Germany. All rights reserved.
 */

import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { BehaviorSubject, Observable, of } from 'rxjs';
import { delay, first, map } from 'rxjs/operators';
import { MasterDetailResource } from '../master-detail/services/master-detail-ressource';
import { User } from './user';

@Injectable()
export class UserService implements MasterDetailResource<User, Params, string> {
  public items: Observable<any[]>;
  public showDetailsViewCloseIcon: Observable<boolean>;
  public pageSize = 500;
  public pageCount = 0;
  public itemCount = 0;
  public currentPage = 0;
  public pages = [];
  sampleData = [
    new User('1', 'Bob', 'Administrator', 'Security', 'Bob@company.com', this.generateEntryDate(50), false),
    new User('2', 'Sarah', 'User', 'Sales', 'Sarah@company.com', this.generateEntryDate(30), false),
    new User('3', 'Michael', 'User', 'Recruiting', 'Michael@company.com', this.generateEntryDate(5), false),
    new User('4', 'Megan', 'User', 'Cloud Development', 'Megan@company.com', new Date(), false),
    new User('5', 'Alice', 'Administrator', 'Infrastructure', 'Alice@company.com', this.generateEntryDate(51), false),
    new User('6', 'Charlie', 'User', 'Security', 'Charlie@company.com', this.generateEntryDate(40), false),
    new User('7', 'Deborah', 'User', 'Sales', 'Deborah@company.com', this.generateEntryDate(43), false),
    new User('8', 'Eric', 'Administrator', 'Infrastructure', 'Eric@company.com', this.generateEntryDate(2), false),
    new User('9', 'Frank', 'User', 'Sales', 'Frank@company.com', this.generateEntryDate(5), false),
    new User('10', 'George', 'User', 'Recruiting', 'George@company.com', this.generateEntryDate(45), false),
    new User('11', 'Mike', 'User', 'Recruiting', 'external.Mike@company.com', this.generateEntryDate(15), false),
  ];
  private readonly _items: BehaviorSubject<any[]>;
  private readonly _showDetailsViewCloseIcon: BehaviorSubject<boolean>;
  private _lastQuery: Params | undefined;

  private static compareUsers(a: User, b: User, attribute: string): number {
    return a.compare(b, attribute);
  }

  constructor() {
    this._items = new BehaviorSubject<any>([]);
    this.items = this._items.asObservable().pipe(
      delay(1000) // fake some latency
    );
    this._showDetailsViewCloseIcon = new BehaviorSubject<boolean>(true);
    this.showDetailsViewCloseIcon = this._showDetailsViewCloseIcon.asObservable().pipe(
      delay(1000) // fake some latency
    );
  }

  toggleCloseIcon(show: boolean){
    this._showDetailsViewCloseIcon.next(show);
  }

  queryDepartments(): Observable<Set<string>> {
    return this.items.pipe(map((items) => new Set(items.map((user) => user.department))));
  }

  querySingle(id: string): Observable<User> {
    return of(this.sampleData.find((value) => value.id === id)).pipe(
      first(),
      delay(500) // fake some latency
    );
  }

  queryAll(params?: Params): Observable<User[]> {
    this._lastQuery = params;

    let page = 0;
    let sortAttribute = 'id';

    if (params) {
      // eslint-disable-next-line no-prototype-builtins
      if (params.hasOwnProperty('page')) {
        page = +params['page'];
      }

      // eslint-disable-next-line no-prototype-builtins
      if (params.hasOwnProperty('sort')) {
        sortAttribute = params['sort'];
      }
    }

    const start = page * this.pageSize;
    const end = start + this.pageSize;

    const selectedItems = this.sampleData
      .sort((a, b) => UserService.compareUsers(a, b, sortAttribute))
      .slice(start, end);

    this.itemCount = selectedItems.length;

    this.computeAvailablePages(page);
    this.currentPage = page;

    this._items.next(selectedItems);
    return this.items;
  }

  upsert(user: User): User {
    const index = this.sampleData.findIndex((value) => value.id === user.id);
    if (index >= 0) {
      this.sampleData[index] = user;
    } else {
      this.sampleData.push(user);
    }
    this.queryAll(this._lastQuery);
    return user;
  }

  remove(users: User[]) {
    this.sampleData = this.sampleData.filter((user) => users.indexOf(user) < 0);
    this.queryAll(this._lastQuery);
  }

  private computeAvailablePages(page: number) {
    this.pageCount = Math.ceil(this.sampleData.length / this.pageSize);
    this.pages.length = 0;
    for (let i = 0; i < this.pageCount; i++) {
      this.pages.push({ index: i, active: i === page });
    }
  }

  private generateEntryDate(daysAgo: number) {
    const date = new Date();
    date.setDate(date.getDate() - daysAgo);
    return date;
  }
}
