import { Injectable, ViewRef } from '@angular/core';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { Observable } from 'rxjs/Observable';

export interface IViewRefWatcher {
  setWatcher(type: string): Observable<ViewRef>;

  unsetWatcher(type: string): Observable<ViewRef>;

  set(type: string, viewRef: ViewRef): void;

  unset(type: string): void;
}

export class ViewRefWatcher implements IViewRefWatcher {
  private subjectsSet: { [key: string]: ReplaySubject<any> } = {};
  private subjectsUnset: { [key: string]: ReplaySubject<any> } = {};

  setWatcher(type: string): Observable<ViewRef> {
    let subjectSet: ReplaySubject<any> = this.getSubjectSet(type);
    return subjectSet.asObservable().debounceTime(500);
  }

  unsetWatcher(type: string): Observable<ViewRef> {
    let subjectUnset: ReplaySubject<any> = this.getSubjectUnset(type);
    return subjectUnset.asObservable().debounceTime(10);
  }

  set(type: string, viewRef: ViewRef): void {
    let subjectSet: ReplaySubject<any> = this.getSubjectSet(type);
    subjectSet.next(viewRef);
  }

  unset(type: string): void {
    let subjectUnset: ReplaySubject<any> = this.getSubjectUnset(type);
    subjectUnset.next(null);
  }

  private getSubjectSet(type: string): ReplaySubject<any> {
    if (this.subjectsSet[type] === undefined) {
      let subjectSet: ReplaySubject<any> = new ReplaySubject<any>();
      this.subjectsSet[type] = subjectSet;
    }
    return this.subjectsSet[type];
  }

  private getSubjectUnset(type: string): ReplaySubject<any> {
    if (this.subjectsUnset[type] === undefined) {
      let subjectUnset: ReplaySubject<any> = new ReplaySubject<any>(1);
      this.subjectsUnset[type] = subjectUnset;
    }
    return this.subjectsUnset[type];
  }
}

@Injectable()
export class ViewRefWatcherService extends ViewRefWatcher {
  constructor() {
    super();
  }
}
