import {
  AfterContentInit,
  ChangeDetectorRef,
  Component,
  ContentChildren,
  ElementRef,
  Input, OnDestroy,
  OnInit,
  QueryList
} from "@angular/core";
import {SliderColumnComponent} from "./slider-column.component";

export class Stage {
  value: number;
  max:  number;
}

@Component({
  selector: 'slider-container',
  template: `
      <div class="uk-grid uk-grid-large uk-flex uk-flex-middle uk-flex-between uk-child-width-1-1" [ngClass]="'uk-child-width-1-' + sliders?.length + '@m'" uk-grid>
          <ng-content></ng-content>
      </div>
      <div *ngIf="navigation === 'progress' &&  stages.length > 0" class="uk-flex uk-flex-center uk-margin-large-top">
          <div  class="uk-width-1-3@m uk-width-1-2@s uk-child-width-1-1 uk-grid uk-grid-small uk-flex-middle" [ngClass]="'uk-child-width-1-' + stages.length" uk-grid>
              <div *ngFor="let stage  of stages; let i=index">
                  <progress (click)="start(i)"  class="uk-progress" [value]="stage.value" [max]="stage.max"></progress>
              </div>
          </div>
      </div>
  `
})
export class SliderContainerComponent implements OnInit, OnDestroy, AfterContentInit {
  private static INTERVAL = 10;
  private static ANIMATION_DURATION = 600; // UIKit progress animation duration

  @ContentChildren(SliderColumnComponent) sliders: QueryList<SliderColumnComponent>;
  @Input()
  navigation: 'progress' | null = null;
  @Input()
  total: number = 0;
  @Input()
  period: number = 3000; // in ms (>= 1000ms)
  @Input()
  infinite: boolean = false;
  @Input()
  parent: HTMLDivElement;
  stages: Stage[] = [];
  time: number = 0;
  interval: any;
  observer: IntersectionObserver;
  initialized: boolean = false;
  stopped: boolean = true;

  constructor(private cdr: ChangeDetectorRef, private element: ElementRef) {
  }

  ngOnInit() {
    this.period = this.period - SliderContainerComponent.ANIMATION_DURATION;
  }

  ngOnDestroy() {
    if(this.observer && typeof IntersectionObserver !== 'undefined') {
      this.observer.disconnect();
    }
  }

  ngAfterContentInit() {
    this.setObserver();
    this.sliders.forEach(slider => {
      slider.setContainer(this);
      slider.navItems.forEach(item => {
        if(this.parent) {
          item.background = getComputedStyle(this.parent).backgroundColor;
        }
      });
    });
  }

  setObserver() {
    if(typeof IntersectionObserver !== 'undefined') {
      let options = {
        root: null,
        rootMargin: '0px',
        threshold: 0.1
      };
      this.observer = new IntersectionObserver(entries => {
        entries.forEach(entry => {
          if (entry.isIntersecting && !this.initialized) {
            this.stopped = false;
            this.start(0);
            this.initialized = true;
          } else {
            this.initialized = false;
            this.stopped = true;
          }
        });
      }, options);
      this.observer.observe(this.element.nativeElement);
    }
  }

  start(time: number) {
    this.stages = [];
    for(let i = 0; i < this.total; i++) {
      this.stages.push({value: (time > i?this.period:(time - i)), max: this.period});
    }
    if(this.interval) {
      clearInterval(this.interval);
    }
    this.cdr.detectChanges();
    this.interval = setInterval(() => {
      let current = Math.floor(time);
      this.stages[current].value += SliderContainerComponent.INTERVAL;
      this.time = current + this.stages[current].value/this.stages[current].max;
      this.sliders.forEach(slider => {
        slider.change(this.time);
      });
      if(this.stages[current].value >= this.stages[current].max) {
        clearInterval(this.interval);
        let next = (current + 1 > this.total - 1)?0:current + 1;
        if(!this.stopped && (this.infinite || next > current)) {
          setTimeout(() => {
            this.start(next);
          }, SliderContainerComponent.ANIMATION_DURATION);
        }
      }
    }, SliderContainerComponent.INTERVAL);
  }
}
