
/// <reference path="util.ts" />
/// <reference path="scripts/typings/jquery/jquery.d.ts" />
/// <reference path="cheatsheet_klassen.ts" />
//declare function require(path: string): any;
//var Promise = require("ts-promise").Promise;
// öäüöä
import G = CheatSheet.GO;

////import Kontakt from "CheatSheet.GO";
//import Kontakt from "cheatsheet_klassen";

module CheatSheetClient {


 var Website1 = "http://www.dotnet-doktor.de";
 //Website1 = 123; // falsch !!!


 $(document).ready(function () {
  console.log("Start...");

  $('#headline').css("color", "red");
  $('#headline').text('Cheat Sheet Demos');

  out("Start");

  out("=============== async/await");

  // erfordert Polyfill: https://www.npmjs.com/package/es6-promise

  function randomDelay(milliseconds: number): Promise<void> {
   return new Promise<void>(resolve => {
    for (let i = 0; i < Math.random() * 9; i++) {
     setTimeout(resolve, milliseconds);
     console.log(".");
    }
   });
  }

  async function aktion(text: string, func: (p: number) => Promise<void>, ms: number) {
   out("Starte: " + text);
   await func(ms);
   out("Beendet: " + text);
  }


  aktion("Aufgaben laden", randomDelay, 500);
  aktion("Kontakte laden", randomDelay, 1000);
  aktion("Termine laden", randomDelay, 700);


  return;
  out("===============  JS-Syntax");
  //var jse1 : any = calc(2, 10,2);
  //out("Ergebnis von e1: " + jse1 + "/" + jse1.wert);
  var jse2: any = calc(2, 10, "x");
  out("Ergebnis von e2: " + jse2);

  out("===============  JS-Syntax: Falsy");
  //JSFalsy();

  out("=================== Typprüfung");


  var eingabe: any = 5;

  if (typeof eingabe === 'number') {
   var zahl1 = (<number>eingabe) + 1;
   // alternativ:
   var zahl2 = (eingabe as number) + 2;
   out("Zahl1:" + zahl1);
   out("Zahl2:" + zahl2);
  }



  out("===============  Klassen nutzen");
  var k1 = new G.Kontakt(123, "Holger Schwichtenberg");
  var ausgabe = k1.toString(true);
  out("k1: " + ausgabe);


  var k = new G.Kunde(123, "Holger Schwichtenberg", 99.98);
  var ausgabe = k.toString();
  out("k: " + ausgabe);

  // Typprüfung
  if (k instanceof CheatSheet.GO.Kontakt) { out("k ist ein Kontakt!"); }
  if (k instanceof CheatSheet.GO.Kunde) { out("k ist ein Kunde!"); }

  out("Nutzung von Enums");
  out(k.toString() + ": Kundenart: " + k.KundenArt);




  // ------------- Destructuring von Objekten
  out("Destructuring von Objekten");
  var a1 = `${k.id}: ${k.name}`;
  out("Objektzugriff: " + a1);
  let { id, name } = k;
  var a2: string = `${id}: ${name}`;

  out("----------------- Template Strings (String Interpolation)(seit 1.4)");
  // Template Strings (String Interpolation)(seit 1.4)


  var template: string = `Kunde #${id} heißt ${name}.`;
  var template2: string = `Kunde #${k.id} heißt ${k.name}.`;
  out(template);
  out(template2);

  out("Destructuring: " + a2);

  var ku1 = new CheatSheet.GO.Kunde(123, "Holger Schwichtenberg", 99.98);

  out("ku1: " + ausgabe);
  var ku2 = new CheatSheet.GO.Kunde(456, "Max M.", 500);
  var ku3 = new CheatSheet.GO.Kunde(789, "Max M.", 500);
  // ------------- Spread-Operator
  out("Spread-Operator");
  let obj1 = { Name: "Holger Schwichtenberg" }
  let obj2 = { firma: "www.IT-Visions.de", Ort: "Essen" }
  let obj12 = { ...obj1, ...obj2 };
  out(`${obj12.Name} arbeitet für ${obj12.firma}`);

  console.log("zusammenfassung", obj12);

  //var glueckszahlen = [12, 18, 24, 34, 41, 42];
  //var glueckszahlen2 = ...glueckszahlen;


  out("=============== Generische Klassen nutzen");
  var v = new CheatSheet.GO.Verbindung<G.Kontakt, G.Kunde>(ku1, ku2);
  var ausgabe2 = v.toString();

  out(ausgabe2);







  out("===============  Arrays mit Objekten");
  var kunden = new Array<CheatSheet.GO.Kunde>();
  for (var i = 1; i <= 20; i++) {
   var umsatz = Math.round(((Math.random() * 10000) + 1) * 100) / 100;

   var k = new CheatSheet.GO.Kunde(i, "Kunde #" + i, umsatz);
   kunden.push(k);
  }

  var sortKunden = kunden.sort((x, y) => x.umsatz - y.umsatz);
  out(`sortKunden: ${sortKunden.length}`);
  for (let k of sortKunden) {
   out(k.toString());
  };


  var filterKunden = kunden.filter(x => x.umsatz < 1000);
  out(`filterKunden: ${filterKunden.length}`);
  for (let k of filterKunden) {
   out(k.toString());
  };


  var summeKunden = kunden.reduce(
   (total, x) => { return total + x.umsatz }, 0);
  out(`summe: ${summeKunden.toFixed(2)}`);

  out("===============  Arrays mit Zahlen");

  type ZahlenArray = number[]; // Array<number> oder oder number[]
  var lottozahlen2: ZahlenArray;

  // Deklaration
  var lottozahlen: Array<number> = [];

  // Initialisierung
  //lottozahlen = [11, 19, 28, 34, 41, 48, 5];

  // Ziehen 6 und Zusatzzahl
  for (var i = 1; i <= 7; i++) {
   var zufall = Math.floor((Math.random() * 49) + 1);
   lottozahlen.push(zufall);
  }

  // Schleife über alle Elemente (seit Version 1.5)
  out("Schleife über alle Elemente");
  for (let z of lottozahlen) {
   out(z);
  };

  out("Schleife über alle Elemente . Variante 2");
  lottozahlen.forEach(x => out(x));


  // Destructuring (seit Version 1.5)
  out("Destructuring");
  let [z1, z2, z3, z4, z5, z6, zusatzzahl] = lottozahlen;
  out(`Zusatzzahl: ${zusatzzahl}`);

  // Letztes Element ermitteln
  zusatzzahl = lottozahlen[6]
  out(`Zusatzzahl: ${zusatzzahl}`);

  // Erste 6 Elemente ermitteln
  var hauptzahlen = lottozahlen.slice(0, 6);
  out(`Hauptzahlen: ${hauptzahlen.length}`);
  for (let z of hauptzahlen) {
   out(z);
  };

  var kleineZahlen = lottozahlen.filter(x => x <= 25);
  out(`kleineZahlen: ${kleineZahlen.length}`);
  for (let z of kleineZahlen) {
   out(z);
  };

  var sortZahlen = lottozahlen.sort((x, y) => x - y);
  out(`sortZahlen: ${kleineZahlen.length}`);
  for (let z of sortZahlen) {
   out(z);
  };

  var quadrate = lottozahlen.map(x => x * x);
  out(`quadrate: ${quadrate.length}`);
  for (let z of quadrate) {
   out(z);
  };

  var summe = lottozahlen.reduce((total, x) => {
   console.log(total, x);
   return total + x;
  });
  out(`summe: ${summe}`);

  //var ersteZahlGroesser10 = lottozahlen.sort((x, y) => x - y).find(x=>x>=10);
  //out(`ersteZahlGroesser10: ${ersteZahlGroesser10}`);



  out("Wertbereich korrekt? " + lottozahlen.every(x => x >= 1 && x <= 49));



  out("===============  Variable Declaration");

  if (true) {
   var x: number = 5;
  }
  out("x=" + x); // Ausgabe x=5 :-( nur Warnung

  //if (true) {
  // let y: string = "Holger S.";
  //}
  //out("y=" + y); // Fehler!

  //const z: boolean = true;
  //z = false; // Fehler!





  var o: Object;
  o = 1;
  o = new G.Kontakt(1, "xxx");

  out("=============== Duck Typing");

  var m = new CheatSheet.GO.Mitarbeiter();
  m.id = 1;
  m.name = "Holger Schwichtenberg";
  // erlaubt: Person und Mitarbeiter passen zueinander! 
  var p: CheatSheet.GO.Person = m;

  out(p.id + ": " + p.name);

  out("=============== Funktionen und Lambda-Ausdrücke");

  function add3(a: number, b: number): number {
   return a + b;
  }

  out("Add: " + add3(2, 5));

  // Funktionstyp deklarieren
  var add: (a: number, b: number) => number;
  // Funktionstyp implementieren
  add = (a, b) => a + b;
  // Funktion nutzen
  const c = add(1, 2);

  // Deklaration und Implementierung zusammen
  var out2 = (s: string) => console.log(s);
  // Typherleitung: Add2 liefert number!
  var add2 = (a: number, b: number) => a + b;

  out("Funktionen als Parameter");

  // Funktionen als Parameter
  function execMathFunc(f: (a: number, b: number) => number, a: number, b: number) {
   return f(a, b);
  }
  var e2 = execMathFunc(add, 2, 3);
  out(e2);

  
  out(c);


  out("=============== Tupel");

  var PersonTupel: [number, string, boolean];
  PersonTupel = [123, "Holger S.", true];
  var personName = PersonTupel[1];
  out(personName);

  out("=============== Union Types");

  var mitarbeiterID: number | string;
  mitarbeiterID = 123; // OK
  mitarbeiterID = "A123"; // auch OK
  //mitarbeiterID = true; // Fehler!

  out("=============== Schnittstellenverschmelzung");



  out("=============== keyof");

  function getProperty<T, K extends keyof T>(obj: T, key: K) {
   return obj[key];  // Inferred type is T[K]
  }

  let obj = { x: 10, y: "hello!" };

  let objX = getProperty(obj, "x"); // number
  let objY = getProperty(obj, "y"); // string
  // FEHLER: let objZ = getProperty(obj, "z"); // string

  out(objX);
  out(objY);
  

  console.log("fertig!");
 });

}