// Spielwiese für verschiedene Beispiele zur Datenbindung

// Angular-Importe
import { Component, OnInit, ChangeDetectionStrategy, OnChanges, SimpleChange, DoCheck, KeyValueDiffers, ChangeDetectorRef } from '@angular/core';
import { Router } from '@angular/router';
import * as Rx from 'rxjs/Observable';

// Importe für eigene Klassen
import { Flug } from '../Modell/Flug'
import { FlugService } from '../Services/FlugService'
import { Flugdetail } from '../Flugdetail/Flugdetail'; // für Event
import { Datengenerator } from '../Services/Datengenerator'; // für Event

@Component({
 selector: 'Flugliste',
 templateUrl: 'App/_misc/Datenbindung.html',
 changeDetection: ChangeDetectionStrategy.Default,
 providers: [FlugService] // Lokale Registrierung eines Dienstes für Dependency Injection
})

export class Datenbindung implements OnInit, OnChanges, DoCheck {
 differ: any;

 // flugSet: Observable<Flug[]> = null;
 timerAsync: any;
 timerSync: any;
 zahlen: number[];
 zahlenO: Rx.Observable<number[]>;

 fluege: Flug[];
 fluegeO: Rx.Observable<Flug[]>;

 fluege2: Flug[];
 fluege2O: Rx.Observable<Flug>;

 flug: Flug;
 flugO: Rx.Observable<Flug>;

 constructor(private flugService: FlugService,
  private router: Router, private differs: KeyValueDiffers, private ref: ChangeDetectorRef) { // hier wird FlugService injeziert
  this.differ = differs.find({}).create(null);

  // Trigger für Update des UI 1x pro Sekunde!
  // this.timerSync = Rx.Observable.interval(1000).startWith(0).subscribe(x => this.timerSync = x);
  // this.timerAsync = Rx.Observable.interval(1000).startWith(0);

  this.zahlen = [1, 2, 3, 4, 5];
  this.zahlenO = Rx.Observable.of(this.zahlen);

  this.fluege = new Datengenerator().getTestData();
  this.fluegeO = Rx.Observable.of(this.fluege);

  this.flugService.getAll(x => this.fluege2 = x);
  this.fluege2O = this.flugService.getAllAsOversable();
  this.flug = this.fluege[0];


 }

 status: string;

 flugSet: Flug[]

 f1: Flug;
 a: Array<Flug>;
 ngOnInit() {
  // this.DatenLaden();

  this.a = new Array<Flug>();
  this.f1 = new Flug();
  this.f1.FlugNr = 101;
  this.f1.FreiePlaetze = 222;
  this.f1.Abflugort = "Rom";
  var f2 = new Flug();
  f2.FlugNr = 102;
  f2.Abflugort = "Rom";
  var f3 = new Flug();
  f3.FlugNr = 103;
  this.a.push(this.f1);
  this.a.push(f2);
  this.a.push(f3);

  var o1: Rx.Observable<Flug>;

  var o2: Rx.Observable<Flug[]>;

  // falsch!
  // o1 = Observable.of(a);
  // o2 = Observable.from(a);

  o1 = Rx.Observable.from(this.a); // jedes Element einzeln in Sequence
  o2 = Rx.Observable.of(this.a); // Array als ein Element in Sequence

  o1.count().subscribe(x => console.log("Anz o1:" + x)); // 3 --> drei Elemente im Observable
  o2.count().subscribe(x => console.log("Anz o2:" + x)); // 1 --> ein Array (mit drei Elementen) in Observable

  var o3 = o2.flatMap(x => x);
  o3.count().subscribe(x => console.log("Anz o3:" + x)); // 1 --> zwei Elemente im Observable

  o3.subscribe(x => console.log("o3", x)); // 1 --> zwei Elemente im 

  var o4 = o2.flatMap(x => x).filter(x => x.FlugNr < 102).toArray();
  o4.count().subscribe(x => console.log("Anz o4:" + x));

  var o5 = Rx.Observable.of(this.a, this.a, this.a, this.a); // Observable mit 4 Arrays
  o5.count().subscribe(x => console.log("Anz o5:" + x));
  o5.subscribe(x => console.log("o5", x)); // 1 --> zwei Elemente im 

  // UI-Bindung
  // tatsächlich erwartet Angular 2 ein Observable, dass ein Array von Flug verpackt :-(
  // this.flugSet = o2;

  // das geht nicht "NgFor only supports binding to Iterables such as Arrays."
  // this.flugSet = o4;
  // this.update0();

   this.fluegeO = o5;
 }

 update0() {
  console.log("Update0 Daten aus Dummy");
  this.flug = this.f1;
  this.fluege = this.a;
  this.fluegeO = Rx.Observable.of(this.a, this.a);
 }


 update1() {
  console.log("Update1 Quellobjekt");
  this.f1.FreiePlaetze--;
  this.a[0].FreiePlaetze--;;
  this.a.pop();

 }


 update2() {
  console.log("Update2 gebundenes Objekt!");
  this.flug.FreiePlaetze--;
  this.fluege[0].FreiePlaetze--;
this.fluege.pop();
 }

 update3() {
  console.log("Update3 aus Datengenerator!");

  this.flugService.getAll(x => this.fluege = x);
  this.fluege = this.flugService.flugSet;
  this.fluegeO = this.flugService.getAllAsOversable();
  this.flug =  this.flugService.flugSet[0];
 }


 update4() {
  console.log("Update4 Quelldaten");

  this.flugService.flugSet[0].FreiePlaetze--;
  this.flugService.deleteById(103);
 }


 // nur zur Diagnose!
 ngOnChanges(changes: { [propName: string]: SimpleChange }) {
  console.log('ngDoCheck: Change detected:', changes);
 }

 // nur zur Diagnose!
 ngDoCheck() {
  var changes = this.differ.diff(this.flugSet);

  if (changes) {
   console.log('ngDoCheck: changes detected', changes);
  } else {
   console.log('ngDoCheck: nothing changed');
  }
 }

 DatenLaden() {
  this.flugService.getAll(daten => {
   this.flugSet = this.flugService.flugSet;
   this.status = this.flugSet.length + " Flüge geladen.";

   // oder wenn Observable hochgereicht wird:
   // this.flugService.getAll().subscribe(x => {  this.flugSet =x; console.log("subscribe...", x);} );

  });
 }

 Loeschen(flug: Flug) {
  this.flugService.delete(flug);
  this.flugSet = this.flugService.flugSet;
  this.status = `Flug ${flug.FlugNr} gelöscht!`;
  console.log("delete(): " + this.flugSet.length);
 }

 onDatenGeaendertEvent(flug: Flug) {
  console.log("EVENT: Flug geändert", flug)
  this.flugSet = this.flugService.flugSet;
 }

 Aendern(flug: Flug) {
  let link = ['/edit', flug.FlugNr];
  this.router.navigate(link);
 }
}