import { Component, HostListener, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ToolConfigs } from '../../lib/filler/tool-config';
import { EditorDirective } from '../../lib/filler/editor.directive';
import { CheckerUploadComponent } from './checker-upload.component';
import { Location } from '@angular/common';
import MapEditLayer from '../../lib/filler/map-edit/map-edit-layer';
import FillArea from '../../lib/filler/common/fillarea';
import Rect from '../../lib/filler/core/rect';
import { ActivatedRoute } from '@angular/router';
import Utils from '../../lib/filler/common/utils';
import Layer from '../../lib/filler/core/layer';
import { UploadBoxComponent } from './upload-box.component';
import { FileDomain, FileInfo } from './interfaces';
import ImageLayer from '../../lib/filler/core/image-layer';
import { Potrace } from '../../lib/filler/common/potrace';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import FloodFill2 from 'src/app/lib/filler/common/floodfill2';

@Component({
  selector: 'art-potrace',
  templateUrl: './potrace.component.html',
  styleUrls: ['./play.component.css']
})
export class PotraceComponent implements OnInit, OnDestroy {

  @HostListener('window:keydown', ['$event'])
  keyEvent(event: KeyboardEvent) {
    let key = parseInt(event.key);
    if (NaN == key) return;
    if (key > 0 && key <= this.layers.length) {
      this.switchLayer(key - 1);
    }
  }


  @ViewChild(EditorDirective)
  editorRef: EditorDirective;


  mapEditLayer: MapEditLayer;

  isUpload: boolean = false;
  showAreaList: boolean = false;

  private id: string;
  layers: LayerInfo[] = [];
  index = 0;

  fi: FileInfo;

  slider: number = 128;

  public readonly fileDomain = FileDomain;

  constructor(
    public location: Location,
    private modalService: NgbModal,
    private router: ActivatedRoute,
  ) {

  }

  ngOnInit() {
    //this.uploadBox._onChange.subscribe(this.onUpload.bind(this));
  }


  get utils() { return Utils };

  get tools(): any[] {
    return this.editorRef.editor.getToolsStatus().map(ts => {
      let config = ToolConfigs[ts.key];
      if (config) Object.assign(ts, config);
      return ts;
    });
  }



  /**
   * 通用打开modal
   * @param content 
   */
  openModal(content) {
    this.modalService.open(content, {
      centered: true,
      size: 'lg',
    })
      .result.then((result) => {
        console.log(`Closed with: ${result}`);
      }, (reason) => {
        console.log(`Dismissed ${reason}`);
      });
  }



  focusToArea(area: FillArea) {
    let rect = new Rect(area.left, area.top, area.right, area.bottom);
    this.editorRef.editor.focusToRect(rect);
    if (this.mapEditLayer) this.mapEditLayer.blinkByAreas([area]);
  }


  async onUpload(fis: FileInfo[]) {
    if (!fis || fis.length <= 0) return;
    this.fi = fis[0];
    this.layers = [];

    this.editorRef.editor.setBackgroundLayer(null);


    //this.addLayer(new ImageLayer(this.fi.image), 'png');
    //this.addLayer(new ImageLayer(this.fi.image), 'potraced');
    //this.addLayer(new ImageLayer(this.fi.image), 'potracedPng');
    //this.addLayer(new ImageLayer(this.fi.image), 'MapLayer');
    if (!this.layers[0]) {
      this.layers[0] = { layer: new ImageLayer(this.fi.image), name: 'raw' };
    } else {
      (this.layers[0].layer as ImageLayer).image = this.fi.image;
    }

    await this.potrace();
  }


  async potrace() {
    let potrace = new Potrace(this.fi.image, { threshold: this.slider });
    let pImage = await Utils.blobToImage(potrace.getBlob(1));

    if (!this.layers[1]) {
      this.layers[1] = { layer: new ImageLayer(pImage), name: 'Potraced' };
    } else {
      (this.layers[1].layer as ImageLayer).image = pImage;
    }

    let pngBlob = await Utils.convertToPngBlob(pImage);
    let png = await Utils.blobToImage(pngBlob);
    if (!this.layers[2]) {
      this.layers[2] = { layer: new ImageLayer(png), name: 'raw' };
    } else {
      (this.layers[2].layer as ImageLayer).image = png;
    }


    let ff = new FloodFill2(png);
    let map = await ff.toImage();

    if (!this.layers[3]) {
      this.layers[3] = { layer: new MapEditLayer(pImage, map), name: 'Map Edit' };
    } else {
      (this.layers[3].layer as MapEditLayer).update(pImage, map);
    }

    if (this.editorRef.editor.getBackgroundLayer() == null) {
      this.switchLayer(0, true);
    }
  }

  onSliderChange() {
    console.log(this.slider);
    this.potrace();
  }


  switchLayer(index: number, bestFit: boolean = false) {
    console.log('Switch Layer:', index);
    this.index = index;
    let layer = this.layers[index].layer;
    this.editorRef.editor.setBackgroundLayer(layer, bestFit);
  }


  ngOnDestroy() {
    this.layers.forEach(layer => layer.layer.destroy())
  }


}


interface LayerInfo {
  layer: Layer;
  name: string;
}

