import {
  Component,
  ChangeDetectionStrategy,
  ElementRef,
  ViewChild,
  NgZone,
  AfterViewInit,
  OnDestroy, OnInit,
} from '@angular/core';
import { BarcodeCapture, BarcodeCaptureSettings, Symbology } from 'scandit-web-datacapture-barcode';
import { Camera, DataCaptureContext, DataCaptureView, FrameSourceState } from 'scandit-web-datacapture-core';

@Component({
  selector: 'app-scandit-overlay',
  templateUrl: 'scandit-overlay.component.html',
  styleUrls: ['scandit-overlay.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: false,
})
export class ScanditOverlayComponent implements AfterViewInit, OnDestroy, OnInit {
  private dataCaptureContext: DataCaptureContext;
  private dataCaptureView: DataCaptureView;
  private barcodeCapture: BarcodeCapture;
  private camera: Camera;

  private _onScan?: (code: string) => void;

  private _onClose?: () => void;

  @ViewChild('scanContainer', { read: ElementRef, static: true }) scanContainer: ElementRef;

  constructor(private _zone: NgZone) {}

  ngOnInit(): void {
    this.dataCaptureView = new DataCaptureView();

    this.dataCaptureView.connectToElement(this.scanContainer.nativeElement);

    this.dataCaptureView.showProgressBar();
  }

  async ngAfterViewInit() {
    this.dataCaptureContext = await DataCaptureContext.create();

    this.dataCaptureView.setContext(this.dataCaptureContext);

    this.barcodeCapture = await BarcodeCapture.forContext(this.dataCaptureContext, this.getScanSettings());

    this.barcodeCapture.addListener({
      didScan: (_, session, __) => {
        this._zone.run(() => {
          const result = session.newlyRecognizedBarcode;

          const code = result?.data ?? '';

          this._onScan?.(code);
        });
      },
    });

    this.camera = Camera.default;

    this.dataCaptureContext.setFrameSource(this.camera);

    await this.camera.switchToDesiredState(FrameSourceState.On);
    this.dataCaptureView.hideProgressBar();
  }

  getScanSettings(): BarcodeCaptureSettings {
    const settings = new BarcodeCaptureSettings();

    settings.enableSymbologies([
      Symbology.EAN8,
      Symbology.EAN13UPCA,
      Symbology.UPCE,
      Symbology.Code128,
      Symbology.Code39,
      Symbology.Code93,
      Symbology.InterleavedTwoOfFive,
      Symbology.QR,
    ]);

    return settings;
  }

  onScan(fn: (code: string) => void) {
    this._onScan = fn;
  }

  onClose(fn: () => void) {
    this._onClose = fn;
  }

  close() {
    this._onClose?.();
  }

  ngOnDestroy(): void {
    this._zone.runOutsideAngular(() => {
      this.barcodeCapture?.setEnabled(false);
      this.camera?.switchToDesiredState(FrameSourceState.Off);
    });
  }
}
