import { Location } from '@angular/common';
import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, HostListener, Injectable, OnDestroy, OnInit, TemplateRef, ViewChild, ViewChildren } from '@angular/core';
import { ActivatedRoute, CanDeactivate } from '@angular/router';
import { EditorDirective } from '../../lib/filler/editor.directive';
import { ArtService } from './art.service';
import NumberEditLayer from '../../lib/filler/number-edit/number-edit-layer';
import ImageLayer from '../../lib/filler/core/image-layer';
import MapEditLayer from '../../lib/filler/map-edit/map-edit-layer';
import { ToolConfig, ToolConfigs } from '../../lib/filler/tool-config';
import OrderEditLayer from '../../lib/filler/order-edit/order-edit-layer';
import FillArea from '../../lib/filler/common/fillarea';
import Rect from '../../lib/filler/core/rect';
import { Centers, ColorInfo, ColorMap, ColorSumItem } from '../../lib/filler/common/interfaces';
import { UploadComponent } from './upload.component';
import { ArtMeta, ArtUpload, FileDomain, FileInfo } from './interfaces';
import Utils from '../../lib/filler/common/utils';
import { NgbModal, NgbTooltipConfig } from '@ng-bootstrap/ng-bootstrap';
import { ColorBoxComponent } from './color-box.component';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalService } from 'ng-zorro-antd/modal';
import Editor from 'src/app/lib/filler/core/editor';
import { HttpDownloadProgressEvent, HttpEvent, HttpEventType, HttpProgressEvent } from '@angular/common/http';
import CheckEditLayer from 'src/app/lib/filler/check-edit/check-edit-layer';
import { firstValueFrom } from 'rxjs';
import MarkEditLayer from 'src/app/lib/filler/mark-edit/mark-edit-layer';


@Injectable()
export class CanDeactivateGuard implements CanDeactivate<PlayComponent>{

  canDeactivate(component: PlayComponent): boolean {
    if (confirm("You have unsaved changes! If you leave, your changes will be lost.")) {
      return true;
    } else {
      return false;
    }
  }
}

const TAG = 'PlayComponent';

@Component({
  selector: 'art-play',
  templateUrl: './play.component.html',
  styleUrls: ['./play.component.css']
})

export class PlayComponent implements OnInit, AfterViewInit, OnDestroy {
  isLoading: boolean = false;
  loadingProgress: HttpProgressEvent;

  // 当前焦点是否在标注输入框内
  isFocusOnMark: boolean = false;

  onMarkItemFocus(idx: number) {
    this.isFocusOnMark = true;
    this.markEditLayer.selectMarkIdx(idx);
  }

  onMarkItemBlur() {
    this.isFocusOnMark = false;
  }
  

  @HostListener('window:keydown', ['$event'])
  keyEvent(event: KeyboardEvent) {

    if (this.nzModal.openModals.length > 0) return;
    if (this.isUpload) return;
    if (this.isFocusOnMark) return;
    let key = event.key.toLocaleLowerCase();
    let isCtrl = event.ctrlKey;
    let isMeta = event.metaKey;
    let isCtrlOrMeta = isCtrl || isMeta;

    console.log(key, isCtrl, isMeta);


    if ('f' == key) {
      Utils.toggleFullscreen(); //全屏
    } else if ('d' == key) {
      this.editorRef.editor.bestFit(); //居中
    } else if (' ' == key) { //space
      this.editorRef.editor.setToolByKey('pan'); //移动工具
      this.updateTools();
    } else if ('z' == key && isCtrlOrMeta) {
      if (this.currentLayer && this.currentLayer.undoSize() > 0) this.currentLayer.undo();
      event.preventDefault();
    } else if ('r' == key && isCtrlOrMeta) {
      if (this.currentLayer && this.currentLayer.redoSize() > 0) this.currentLayer.redo();
      event.preventDefault();
    } else if ('q' == key && (this.isNumberEdit || this.isMapEdit || this.isCheckEdit)) { //隐藏线稿 
      if (this.isNumberEdit) this.numberEditLayer.hideLine = !this.numberEditLayer.hideLine;
      if (this.isMapEdit) this.mapEditLayer.showPage = !this.mapEditLayer.showPage;
      if (this.isCheckEdit) this.checkEditLayer.togglePage();
      event.preventDefault();
    } else if ('s' == key && isCtrlOrMeta) {
      this.onSave();
      event.preventDefault();
    } else if ('v' == key) { //toggle svg
      if (this.currentLayer) this.currentLayer.showSvg = !this.currentLayer.showSvg;
    } else if ('p' == key) { //toggle svg
      if (this.currentLayer) this.currentLayer.smoothing = !this.currentLayer.smoothing;
    } else if ('r' == key) {
      this.editorRef.editor.reset100(); //100%
    } else if ('h' == key) { // 展示当前上色效果，定位到‘移动’按钮
      if (this.currentLayer === this.numberEditLayer) {
        this.numberEditLayer.showUnorderMask = false;
        this.editorRef.editor.setToolByKey('pan');
        this.updateTools();
        this.numberEditLayer.invalidate();
      }
    } else if ('c' == key || '1' == key) {
      this.switchLayer(EditType.number);
    } else if ('m' == key || '2' == key) {
      this.switchLayer(EditType.map);
    // } else if ('o' == key || '3' == key) {
    //   this.switchLayer(EditType.order)
    } else if ('3' == key) {
      this.switchLayer(EditType.rawColored)
    } else if ('4' == key) {
      this.switchLayer(EditType.check);
    } else if ('5' == key) {
      this.switchLayer(EditType.mark);
    } else {
      if (this.toolShotcuts && this.toolShotcuts[key]) {
        let toolConfig: ToolConfig = this.toolShotcuts[key];
        if (toolConfig.isCtrl && isCtrlOrMeta || !toolConfig.isCtrl) {
          this.editorRef.editor.setToolByKey(toolConfig.key);
          this.updateTools();
          event.preventDefault();
        }
      }
    }

  }

  //@ViewChild('.active') activeColorBox: ElementRef;
  @ViewChildren(ColorBoxComponent) colorBoxes: ColorBoxComponent[];


  @ViewChild(EditorDirective)
  editorRef: EditorDirective;

  @ViewChild(UploadComponent)
  uploadRef: UploadComponent;


  R: number = 1;
  N: number = 10;

  edit: EditType;
  id: string;
  doc: any;

  isUpload: boolean = false;

  dataInput: EditorInputData;
  dataOutput: EditorOutputData = {};

  numberEditLayer: NumberEditLayer;
  mapEditLayer: MapEditLayer;
  orderEditLayer: OrderEditLayer;
  checkEditLayer: CheckEditLayer;
  markEditLayer: MarkEditLayer;
  rawColoredLayer: ImageLayer;

  showAreaList: boolean = false;

  showImageColorPicker: boolean = false;

  constructor(
    public modalService: NgbModal,
    private _location: Location,
    private router: ActivatedRoute,
    private artService: ArtService,
    private message: NzMessageService,
    private nzModal: NzModalService,
    private cdr: ChangeDetectorRef,
  ) {
    this.id = this.router.snapshot.paramMap.get('id');
    this.edit = (this.router.snapshot.paramMap.get('edit') as EditType) || EditType.number;
    console.log('default edit:', this.edit);
  }

  async ngAfterViewInit() {
    await this.editorRef.editor.ready;
    this.editorRef.editor.on('pick-color', (editor: Editor, color: string) => {
      this.setNumberEditLayerColor(color)
      this.scrollToActiveColorBox();
    });

    if (this.id) {
      !Utils.isFullscreen() && Utils.toggleFullscreen();
      this.isUpload = false;
      this.isLoading = true;
      this.artService.getAll(this.id, true).subscribe({
        next: (event: HttpEvent<any>) => {
          if (event.type === HttpEventType.DownloadProgress) {
            this.loadingProgress = event;
          }
          if (event.type === HttpEventType.Response) {
            this.doc = event.body;
            this.onRemoteData();
            setTimeout(() => {
              this.isLoading = false;
            }, 1000);
          }
        },
        error: err => {
          this.message.error(err.error?.message || err.message);
          this.isLoading = false;
        },
      });
    } else {
      //show upload
      this.isUpload = true;
    }
  }


  async ngOnInit() {
    firstValueFrom(this.artService.sysConfig())
    .then((ret: any) => {
      this.R = ret.Rmin;
      this.N = ret.Nmax;
    })
  }

  ngAfterContentChecked() {
    this.cdr.detectChanges();
  }


  /**
   * 上传文件
   * @param fis 文件列表
   */
  async onUpload(artUpload: ArtUpload) {
    !Utils.isFullscreen() && Utils.toggleFullscreen();
    let { artMeta, fis } = artUpload;
    this.dataOutput.artMeta = artMeta;

    let input = {};

    //收集所有的meta信息,并将 blob存储到dataOutput, image/object传递到 dataInput
    fis.forEach(fi => {
      if (!fi) return;

      if (fi.artMeta) {
        Object.assign(this.dataOutput.artMeta, fi.artMeta);
      }
      this.dataOutput[fi.domain] = fi.blob;
      if (fi.blob.type.startsWith('image')) {
        input[fi.domain] = fi.image;
      } else if (fi.blob.type.startsWith('application/json')) {
        input[fi.domain] = fi.object;
      }
    })


    this.dataInput = input as EditorInputData;

    console.log('dataInput:', this.dataInput);

    this.switchLayer(this.edit, true);
    console.log('dataOutput:', this.dataOutput);

    //关闭上传界面
    this.isUpload = false;
  }



  async onRemoteData() {
    console.log(TAG, 'onRemoteData', this.doc);
    if (!this.doc) return;

    let input = {};
    let artBins: ArtBin[] = (Object.values(this.doc).filter((prop: any) => prop && prop.type)) as ArtBin[];
    console.log('artBins', Object.values(artBins));
    for (var i = 0; i < artBins.length; i++) {
      let bin = artBins[i];
      if (bin.mime.startsWith('image')) {
        input[bin.type] = await Utils.base64ToImage(bin.data_base64, bin.mime)
      } else if (bin.mime.startsWith('application/json')) {
        input[bin.type] = bin.data_json;
      }
    }

    // 如果centersVersion与mapVersion不匹配，则不用centers
    if (input['centers'] && this.doc.centersVersion != this.doc.mapVersion) delete input['centers'];

    this.dataInput = input as EditorInputData;

    console.log(TAG, 'onRemoteData@dataInput', this.dataInput);

    this.switchLayer(this.edit, true);
  }



  switchLayer(editType: EditType, bestFit: boolean = false) {
    if (!this.dataInput) {
      console.warn(TAG, 'no input data, can not switch ');
      return;
    }

    let { page, map, colorMap, raw, colorOrder, orderAuto, rawColored, special, centers, mark } = this.dataInput;

    if (EditType.map == editType) {

      if (!this.mapEditLayer) {
        this.mapEditLayer = new MapEditLayer(page, map, raw);
        this.mapEditLayer.on('unload', this.onMapEditUnload.bind(this))
        this.mapEditLayer.on('map-update', this.onMapEditUpdate.bind(this));
      }
      this.editorRef.editor.setBackgroundLayer(this.mapEditLayer, bestFit);

    } else if (EditType.number == editType) {

      if (!this.numberEditLayer) {
        this.numberEditLayer = new NumberEditLayer(this.message, page, map, colorMap, colorOrder, centers, raw);
        this.numberEditLayer.on('edit-update', this.onNumberEditUpdate.bind(this));
        this.numberEditLayer.on('unload', this.onNumberEidtUnload.bind(this));
        if (this.doc?.mystery) { // 如果是神秘图则默认隐藏线稿
          this.numberEditLayer.mystery = true;
          this.numberEditLayer.hideLine = true;
        }
      }
      this.editorRef.editor.setBackgroundLayer(this.numberEditLayer, bestFit);

    } else if (EditType.order == editType) {

      if (!this.orderEditLayer) {
        this.orderEditLayer = new OrderEditLayer(page, map, colorMap, colorOrder, orderAuto, centers, raw);
        this.orderEditLayer.on('edit-update', this.onOrderEditUpdate.bind(this));
        this.orderEditLayer.on('unload', this.onOrderEditUnload.bind(this));
      }
      this.editorRef.editor.setBackgroundLayer(this.orderEditLayer, bestFit);
    } else if (EditType.check == editType) {

      if (!this.checkEditLayer) {
        this.checkEditLayer = new CheckEditLayer(raw, page, map, centers, this.R, this.N);
      }
      this.editorRef.editor.setBackgroundLayer(this.checkEditLayer, bestFit);

    } else if (EditType.mark == editType) {
      if(!this.markEditLayer) {
        this.markEditLayer = new MarkEditLayer(raw, page, map, colorMap, mark);
      }
      this.markEditLayer.on('edit-update', this.onMarkEditUpdate.bind(this));
      this.editorRef.editor.setBackgroundLayer(this.markEditLayer, bestFit);
    } else if (EditType.rawColored == editType) {
      let image = rawColored || special;
      if (!image) {
        this.message.warning($localize`没有special或者colored`);
        return;
      }

      if (!this.rawColoredLayer) {
        this.rawColoredLayer = new ImageLayer(image);
      }
      this.editorRef.editor.setBackgroundLayer(this.rawColoredLayer, bestFit);
    } 
    //this.dumpToolStatus();
    this.updateTools();
  }

  async onMapEditUnload() {
    if (this.mapEditLayer.isSaved()) return;
    let map = await this.mapEditLayer.getMapImage();
    this.mapEditLayer.setSaved();
    this.numberEditLayer && this.numberEditLayer.update(null, map);
    this.orderEditLayer && this.orderEditLayer.update(null, map);
    this.checkEditLayer && this.checkEditLayer.update(null, map);
    this.markEditLayer && this.markEditLayer.update(null, null, map);
    this.dataInput.map = map; //update data input
  }

  async onNumberEidtUnload() {
    if (this.dataInput.colorMap != this.numberEditLayer.colorMap ||
      this.dataInput.colorOrder != this.numberEditLayer.colorOrder) {
      this.dataInput.colorMap = this.numberEditLayer.colorMap; // update data input.
      this.dataInput.colorOrder = this.numberEditLayer.colorOrder;
      this.markEditLayer && this.markEditLayer.update(null, null, null, this.numberEditLayer.colorMap);
    }
  }

  async onOrderEditUnload() {
    if (!this.dataInput.centers) {
      this.dataInput.centers = this.orderEditLayer.centers; // update centers 
    }
    if (this.dataInput.colorOrder != this.orderEditLayer.colorOrder) {
      this.dataInput.colorOrder = this.orderEditLayer.colorOrder;
    }
    this.orderEditLayer.playStop();
  }


  async onNumberEditUpdate() {
    //return false;
    this.scrollToActiveColorBox();
    this.dataOutput = this.dataOutput || {};
    this.dataOutput.work = await this.numberEditLayer.getWorkBlob();
    this.dataOutput.colorMap = new Blob([JSON.stringify(this.numberEditLayer.colorMap)], { type: 'application/json' });
    this.dataOutput.colorSum = new Blob([JSON.stringify(this.numberEditLayer.colorSum)], { type: 'application/json' });
    this.dataOutput.colorOrder = new Blob([JSON.stringify(this.numberEditLayer.colorOrder)], { type: 'application/json' });
    if (this.numberEditLayer.centers) {
      this.dataOutput.centers = new Blob([JSON.stringify(this.numberEditLayer.centers)], { type: 'application/json' });
      this.checkEditLayer && this.checkEditLayer.update(null, null, null, this.numberEditLayer.centers);
    }
    this.dataOutput.artMeta = this.dataOutput.artMeta || {}
    this.dataOutput.artMeta.coloredAreaCount = Object.keys(this.numberEditLayer.colorMap).length;
    this.dataOutput.artMeta.colorCount = this.numberEditLayer.colorSum.length;
    this.dataOutput.artMeta.orderedColorCount = this.numberEditLayer.colorOrder.length;
    //this.cdr.detectChanges();
    this.cdr.markForCheck();
    console.log(TAG, 'onNumberEditUpdate', this.dataOutput);
  }

  async onMapEditUpdate() {
    this.dataOutput = this.dataOutput || {};
    this.dataOutput.map = await this.mapEditLayer.getMapBlob();
    this.dataOutput.artMeta = this.dataOutput.artMeta || {};
    this.dataOutput.artMeta.areaCount = this.mapEditLayer.getAreaCount();
    console.log(TAG, 'onMapEditUpdate', this.dataOutput);
  }

  async onMarkEditUpdate() {
    this.dataOutput = this.dataOutput || {};
    this.dataOutput.mark = new Blob([JSON.stringify(this.markEditLayer.marks)], {type: 'application/json'});
    this.dataOutput.markImg = await this.markEditLayer.getMarkBlob();
    console.log(TAG, 'onMarkEditUpdate', this.dataOutput);
  }

  onOrderEditUpdate() {
    this.dataOutput.colorOrder = new Blob([JSON.stringify(this.orderEditLayer.colorOrder)], { type: 'application/json' });
    this.dataOutput.artMeta = this.dataOutput.artMeta || {};
    this.dataOutput.artMeta.orderedColorCount = this.orderEditLayer.colorOrder.length;
    console.log(TAG, 'onOrderEditUpdate', this.dataOutput);
  }

  dumpToolStatus() {
    console.log('tool statuses:', this.editorRef.editor.getToolsStatus())
  }

  async goback() {
    if (this.hasUpdates) {

      this.nzModal.confirm({
        nzTitle: $localize`还有尚未保存的修改, 确定要退出?`,
        //nzContent: '<b style="color: red;">Some descriptions</b>',
        nzOkText: $localize`继续退出`,
        nzOkType: 'dashed',
        nzOkDanger: true,
        nzOnOk: () => this.forceExit(),
        nzCancelText: $localize`取消`,
        nzOnCancel: () => console.log('Cancel')
      });


      //if (res.value) this.forceExit();
    } else {
      this.forceExit();
    }
  }


  forceExit() {
    Utils.isFullscreen() && Utils.toggleFullscreen();
    this._location.back();
  }

  get utils() { return Utils }
  get editTypes() { return EditType }


  tools: any[];
  toolShotcuts: { [key: string]: ToolConfig };

  updateTools(): void {
    this.tools = this.editorRef.editor.getToolsStatus().map(ts => {
      let config = ToolConfigs[ts.key];
      if (config) Object.assign(ts, config);
      return ts;
    });
    console.log(this.tools);
    this.toolShotcuts = this.tools.reduce((r, c: ToolConfig) => {
      if (c.shortcut) { r[c.shortcut] = c; }
      return r;
    }, {});
  }



  get currentLayer() { return this.editorRef?.editor.getBackgroundLayer() }
  get isNumberEdit() { return this.numberEditLayer && this.editorRef.editor.getBackgroundLayer() == this.numberEditLayer }
  get isMapEdit() { return this.mapEditLayer && this.editorRef.editor.getBackgroundLayer() == this.mapEditLayer }
  get isOrderEdit() { return this.orderEditLayer && this.editorRef.editor.getBackgroundLayer() == this.orderEditLayer }
  get isCheckEdit() { return this.checkEditLayer && this.editorRef.editor.getBackgroundLayer() == this.checkEditLayer }
  get isRawColoredLayer() { return this.rawColoredLayer && this.editorRef.editor.getBackgroundLayer() == this.rawColoredLayer }
  get isMarkEdit() { return this.markEditLayer && this.editorRef.editor.getBackgroundLayer() == this.markEditLayer }


  /**
   * css style color
   * @param color 
   */
  setNumberEditLayerColor(color: string) {
    if (this.numberEditLayer) this.numberEditLayer.color = color;
  }
  setOrderEditLayerColor(color: string) {
    if (this.orderEditLayer) this.orderEditLayer.color = color;
  }
  //color box select
  onSelectColor(cssColor: string) {
    if (this.currentLayer == this.numberEditLayer) {
      this.setNumberEditLayerColor(cssColor); 
    } else if (this.currentLayer == this.orderEditLayer) {
      this.setOrderEditLayerColor(cssColor);
    }
  }

  onBlinkByColor(cssColor: string, idx: number) {
    let rect; 
    if (this.currentLayer == this.numberEditLayer) {
      if (this.currentLayer.lastToolKey == 'number-edit-play') { // 播放模式下双击color-box则播放到该位置
        this.numberEditLayer.playPos(idx);
      } else {
        rect = this.numberEditLayer.blinkByColor(cssColor);
      }
    } else if (this.currentLayer == this.orderEditLayer) {
      rect = this.orderEditLayer.blinkByColor(cssColor);
    }
    if (rect) {
      this.editorRef.editor.focusToRect(rect);
    }
  }

  scrollToActiveColorBox() {
    let active = this.colorBoxes.find(box => {
      return box.data.color == this.numberEditLayer.colorInt;
    });
    console.log('Active color box:', active);
    if (active) {
      active.boxRef.nativeElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
  }

  // 整体修改区域颜色 color-change
  colorChangeAreas: number[] = null;
  colorChangeCpToggle = false;
  onChangeColor(destColor) {
    if (!this.colorChangeAreas) return;
    console.log('change areas colors. areas=', this.colorChangeAreas, 'destDolor=', destColor);
    this.numberEditLayer.changeAreasColor(this.colorChangeAreas, destColor);
    this.onSelectColor(destColor);
  }
  onStartChangeColor(areas) {
    this.colorChangeCpToggle = true;
    this.colorChangeAreas = areas;
    this.numberEditLayer.backupOutput();
  }
  onColorChangeCpToggleChange(toggle) {
    console.log('toggle change:', toggle);
    if (!toggle) {
      this.colorChangeAreas = null;
      this.numberEditLayer.editUpdate();
    }
  }


  /**
   * 编辑器聚焦到填色区域
   * @param area 
   */
  focusToArea(area: FillArea) {
    let rect = new Rect(area.left, area.top, area.right, area.bottom);
    this.editorRef.editor.focusToRect(rect);
    if (this.numberEditLayer) this.numberEditLayer.blinkByAreas([area]);
    if (this.mapEditLayer) this.mapEditLayer.blinkByAreas([area]);
    if (this.checkEditLayer) this.checkEditLayer.blinkByAreas([area]);
  }


  isSaving: boolean = false;
  get hasUpdates(): boolean { return this.dataOutput && Object.keys(this.dataOutput).length > 0 }

  //save.
  onSave() {
    if (!this.hasUpdates) { this.message.warning($localize`没啥更新！`); return; }
    if (this.isSaving) { this.message.warning($localize`保存中！`); return; }
    //取消保存限制
    //if (this.isMapEdit) { swal('请切换到填色界面保存！'); return; }

    if (this.id) {
      this.isSaving = true;
      this.updateSave();
    } else {
      this.initialSave();
    }
  }


  /**meta edit */
  @ViewChild('meta') meta: TemplateRef<any>;
  onMetaSuccess(meta: any) {
    meta.tags.unshift(meta.category);
    Object.assign(this.dataOutput.artMeta, meta);
    this.initialSave();
  }

  /**
   * 初次保存
   * @returns 
   */
  private async initialSave() {
    let isMetaReady = this.dataOutput.artMeta && this.dataOutput.artMeta.tags && this.dataOutput.artMeta.name;

    if (!isMetaReady) {
      this.nzModal.create({
        nzContent: this.meta,
        nzTitle: $localize`基础信息`,
        nzFooter: null,
      });
      return;
    }

    this.isSaving = true;

    let form = this.getFormData();
    this.artService.create(form).toPromise()
      .then((res: any) => {
        this.dataOutput = {};
        this.id = res._id;
        console.log(TAG, 'initialSave#res=', res);
        this.message.success($localize`保存成功!`)
      })
      .catch(err => {
        console.error(TAG, 'initialSave#error', err);
        this.message.error($localize`保存失败:${err.error?.message || err.message}`)
      })
      .then(() => { this.isSaving = false; })
  }

  private async updateSave() {
    let form = this.getFormData();
    firstValueFrom(this.artService.update(form, this.id))
      .then((res: any) => {
        this.dataOutput = {};
        //this.id = res._id;
        console.log(TAG, 'update#res=', res);
        this.message.success($localize`保存成功!`);
      })
      .catch(err => {
        console.error(TAG, 'updateSave#error', err);
        this.message.error($localize`保存失败:${err.error?.message || err.message}`)
      })
      .then(() => { this.isSaving = false; })
  }

  private getFormData(): FormData {
    let form = new FormData();
    //blob
    Object.keys(this.dataOutput).forEach(key => {
      if (this.dataOutput[key] instanceof Blob) { //all binary files
        form.set(key, this.dataOutput[key]);
      }
    })
    //meta
    if (this.dataOutput.artMeta) {
      Object.keys(this.dataOutput.artMeta).forEach(key => form.set(key, this.dataOutput.artMeta[key]))
    }

    // 拒稿状态下，仍可以修改拒稿标注
    if (form.has('mark') && form.has('markImg') && this.doc.status == 500) {
      form.set('ignoreStatus', '1');
    }
    
    return form;
  }


  updateDomain: FileDomain;
  get domains() { return FileDomain }

  openUpdateModal(content, domain: FileDomain) {
    this.updateDomain = domain;
    this.modalService.open(content, {
      centered: true,
    })
      .result.then((result) => {
        console.log(`Closed with: ${result}`);
      }, (reason) => {
        console.log(`Dismissed ${reason}`);
      });
  }

  onUpdateConfirmed(fis: FileInfo[]) {
    console.log('onUpdate Confirmed:', fis);

    this.dataOutput = this.dataOutput || {};
    this.dataOutput.artMeta = this.dataOutput.artMeta || {};

    console.log('fis:', fis);
    let updates = {};
    fis.forEach((fi: FileInfo) => {
      if (fi.artMeta) {
        Object.assign(this.dataOutput.artMeta, fi.artMeta);
      }
      this.dataOutput[fi.domain] = fi.blob;
      if (fi.blob.type.startsWith('image')) {
        updates[fi.domain] = fi.image;
        this.dataInput[fi.domain] = fi.image;
      } else if (fi.blob.type.startsWith('application/json')) {
        updates[fi.domain] = fi.object;
        this.dataInput[fi.domain] = fi.object;
      }
    })

    let { page, map, raw, colorMap, colorOrder, special, rawColored, centers } = (updates as EditorInputData);

    this.numberEditLayer && this.numberEditLayer.update(page, map, colorMap, colorOrder, raw, centers);
    this.mapEditLayer && this.mapEditLayer.update(page, map, raw);
    this.orderEditLayer && this.orderEditLayer.update(page, map, colorMap, colorOrder, raw);
    this.checkEditLayer && this.checkEditLayer.update(page, map, raw, centers);
    this.markEditLayer && this.markEditLayer.update(page, raw, map, colorMap);
    if (this.rawColoredLayer) {
      // this.rawColoredLayer.image = special || rawColored;  // 有bug，更新的是线稿，special和rawColored压根都是空的，不应该更新, 改成以下：
      this.rawColoredLayer.image = special || rawColored || this.rawColoredLayer.image;
    }
  }



  modalTitle(key: string) {
    let title = '';
    switch(key) {
    case 'update_raw':
      title = $localize`更新线稿`;
      break;
    case 'update_special':
      title = $localize`更新彩绘`;
      break;
    case 'update_rawColored':
      title = $localize`更新上色底稿`;
      break;
    case 'color_merge_modal':
      title = $localize`颜色合并`;
      break;
    default:
      break;
    }
    return title;
  }

  /**
   * 通用打开modal
   * @param content 
   */
  openModal(content: TemplateRef<any>, title: string, width: number = 600) {
    this.nzModal.create({
      nzContent: content,
      nzTitle: title,
      nzFooter: null,
      nzWidth : width,
    })
    /*
    this.modalService.open(content, {
      centered: true,
      size: 'lg',
    })
      .result.then((result) => {
        console.log(`Closed with: ${result}`);
      }, (reason) => {
        console.log(`Dismissed ${reason}`);
      });
      */
  }





  ngOnDestroy(): void {
    if (this.numberEditLayer) this.numberEditLayer.destroy();
    if (this.mapEditLayer) this.mapEditLayer.destroy();
    if (this.orderEditLayer) this.orderEditLayer.destroy();
    if (this.checkEditLayer) this.checkEditLayer.destroy();
    if (this.rawColoredLayer) this.rawColoredLayer.destroy();
    this.numberEditLayer = null;
    this.mapEditLayer = null;
    this.orderEditLayer = null;
    this.checkEditLayer = null;
    this.rawColoredLayer = null;
  }

}


export interface EditorInputData {
  org: HTMLImageElement,
  page: HTMLImageElement,
  map: HTMLImageElement,
  special?: HTMLImageElement,
  rawColored?: HTMLImageElement,
  raw?: HTMLImageElement,
  colorMap?: ColorMap,
  colorOrder?: any,
  orderAuto?: any,
  centers ?: Centers,
  mark ?: any,
}

export interface EditorOutputData {
  org?: Blob, //原始线稿
  raw?: Blob, //svg 
  page?: Blob, //page png
  map?: Blob,
  work?: Blob, //上色效果
  colorMap?: Blob,
  colorSum?: Blob,
  colorOrder?: Blob,
  centers?: Blob,
  special?: Blob, //spedial png
  artMeta?: ArtMeta;
  mark ?: Blob,
  markImg ?: Blob,
}


export enum EditType {
  map = 'map-edit',
  number = 'number-edit',
  order = 'order-edit',
  rawColored = 'rawColored', //查看上色图
  check = 'check-edit',
  mark = 'mark-edit',
}

export interface ArtBin {
  mime: string,
  type: string,
  data_json?: any,
  data_base64?: string,
}
