import { Directive, Attribute, Renderer2, ElementRef, Input, HostListener, isDevMode, OnDestroy } from '@angular/core';
import { Router, ActivatedRoute, UrlTree } from '@angular/router';
import { QueryParamsHandling } from '@angular/router/src/config';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';

@Directive({
  selector: ':not(a)[routerLinkDelay]',
  exportAs: 'routerLinkDelay'
})
export class RouterLinkDelayDirective implements OnDestroy {
  @Input() set routerLinkDelay(commands: any[] | string) {
    if (commands != null) {
      this.commands = Array.isArray(commands) ? commands : [commands];
    } else {
      this.commands = [];
    }
  }

  @Input() delay: number = 1000;
  @Input() queryParams: { [k: string]: any };
  @Input() fragment: string;
  @Input() queryParamsHandling: QueryParamsHandling;
  @Input() preserveFragment: boolean;
  @Input() skipLocationChange: boolean;
  @Input() replaceUrl: boolean;

  private commands: any[] = [];
  private preserve: boolean;
  private ngUnsubscribe: Subject<void> = new Subject<void>();

  constructor(private router: Router, private route: ActivatedRoute,
              @Attribute('tabindex') tabIndex: string, renderer: Renderer2, el: ElementRef) {
    if (tabIndex == null) {
      renderer.setAttribute(el.nativeElement, 'tabindex', '0');
    }
  }

  ngOnDestroy(): void {
    this.ngUnsubscribe.next();
    this.ngUnsubscribe.complete();
  }

  @Input()
  set preserveQueryParams(value: boolean) {
    if (isDevMode() && <any>console && <any>console.warn) {
      console.warn('preserveQueryParams is deprecated!, use queryParamsHandling instead.');
    }
    this.preserve = value;
  }

  @HostListener('click')
  onClick(): boolean {
    const extras: any = {
      skipLocationChange: attrBoolValue(this.skipLocationChange),
      replaceUrl: attrBoolValue(this.replaceUrl)
    };
    Observable.timer(this.delay).takeUntil(this.ngUnsubscribe).subscribe((): void => {
      this.ngUnsubscribe.next();
      this.router.navigateByUrl(this.urlTree, extras);
    });
    return false;
  }

  get urlTree(): UrlTree {
    return this.router.createUrlTree(this.commands, {
      relativeTo: this.route,
      queryParams: this.queryParams,
      fragment: this.fragment,
      preserveQueryParams: attrBoolValue(this.preserve),
      queryParamsHandling: this.queryParamsHandling,
      preserveFragment: attrBoolValue(this.preserveFragment)
    });
  }
}

function attrBoolValue(s: any): boolean {
  return s === '' || !!s;
}
