import { CdkConnectedOverlay } from '@angular/cdk/overlay';
import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  EventEmitter,
  Input,
  Output,
  TemplateRef,
  ViewChild,
  ViewEncapsulation
} from '@angular/core';
import { DEFAULT_TOOLTIP_POSITIONS, POSITION_MAP } from 'ng-zorro-antd/core/overlay';
import { ILabelingEvent, ISafeAny } from './label.type';

const OVERLAY_WIDTH = 468;
const OVERLAY_HEIGHT = 288;

@Component({
  selector: 'bixi-label-modal',
  template: `
  <div [ngStyle]="originStyle" cdkOverlayOrigin #trigger="cdkOverlayOrigin">
  </div>
  <ng-template
    #overlay="cdkConnectedOverlay"
    cdkConnectedOverlayBackdropClass="bixi-label-modal-backdrop"
    cdkConnectedOverlay
    [cdkConnectedOverlayOrigin]="trigger"
    [cdkConnectedOverlayHasBackdrop]="true"
    [cdkConnectedOverlayPositions]="positions"
    [cdkConnectedOverlayOpen]="isOpen"
    [cdkConnectedOverlayPush]="true"
    [cdkConnectedOverlayMinHeight]="overlayHeight"
    [cdkConnectedOverlayMinWidth]="overlayWidth"
    [cdkConnectedOverlayOffsetX]="0"
    [cdkConnectedOverlayOffsetY]="-10"
    (backdropClick)="onClose()"
    (detach)="onDetach()"
  >
    <div class="bixi-label-modal" [ngStyle]="overlayStyle"  cdkDrag [cdkDragBoundary]="dragBoundary || 'body'">
      <div class="bixi-label-modal-header" cdkDragHandle>
        <div class='bixi-label-modal-header-inner'>
          <div  class="bixi-label-modal-title">{{title}}</div>
          <div class="bixi-label-modal-close-icon" (click)="onClose()">
            <i nz-icon nzType="close" nzTheme="outline"></i>
          </div>
        </div>
      </div>
      <div class="bixi-label-modal-content">
        <ng-template
          [ngTemplateOutlet]="content"
          [ngTemplateOutletContext]="{$implicit: labeling, labeling: labeling, labels: labels, close: onClose }">
        </ng-template>
      </div>
    </div>
  </ng-template>
  `,
  exportAs: 'bixiLabelModal',
  encapsulation: ViewEncapsulation.None,
  preserveWhitespaces: true,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class BixiLabelModalComponent {
  overlayWidth = OVERLAY_WIDTH;
  overlayHeight = OVERLAY_HEIGHT;
  placement = 'right';
  isOpen = false;
  _labeling: ILabelingEvent | null = null;
  @ViewChild('overlay', { static: false }) overlay!: CdkConnectedOverlay;
  @Input() content: TemplateRef<ISafeAny> | undefined;
  @Input() title: string;
  @Input() dragBoundary: string;
  @Input()
  set labeling(val: ILabelingEvent | null) {
    this._labeling = val;
    if (val) {
      this.onShow();
    } else {
      this.onHide();
    }
  }
  get labeling() {
    return this._labeling;
  }

  // tslint:disable-next-line: no-output-native
  @Output() close = new EventEmitter();

  constructor(
    private cdr: ChangeDetectorRef
  ) { }

  get labels() {
    return this.labeling ? (this.labeling.data) || [] : [];
  }


  onShow() {
    if (this.isOpen && this.overlay) {
      // 如果是二次标注的话，只需要调整位置就可以了
      Promise.resolve().then(() => {
        this.cdr.detectChanges();
        this.overlay.overlayRef.updatePosition();
      });
      return;
    }
    this.isOpen = true;
    this.cdr.detectChanges();
  }

  onHide() {
    this.isOpen = false;
    this.cdr.detectChanges();
  }

  onClose = () => {
    this.onHide();
    this.close.emit();
  }

  onDetach() {
    // 其它方式关闭的话，也触发一次 cancel
    if (this.isOpen) {
      this.onClose();
    }
  }

  get overlayStyle() {
    return {
      width: `${this.overlayWidth || 0}px`,
      height: `${this.overlayHeight || 0}px`
    };
  }

  get positions() {
    return [POSITION_MAP[this.placement], ...DEFAULT_TOOLTIP_POSITIONS];
  }

  get originStyle() {
    if (!this.labeling) {
      return {
        'width': '0px',
        'height': '0px'
      };
    }
    return {
      position: 'absolute',
      width: '20px',
      height: '20px',
      top: `${this.labeling.position.top || 0}px`,
      left: `${this.labeling.position.left || 0}px`
    };
  }
}
