import {Component, NgZone, OnInit, ViewChild, ElementRef} from '@angular/core';
import {ErrorResponse} from '@org_frc971/scouting/webserver/requests/messages/error_response_generated';
import {ActionsSubmitter} from '@org_frc971/scouting/www/rpc';
import {Builder, ByteBuffer} from 'flatbuffers';
import * as pako from 'pako';

declare var cv: any;
declare var Module: any;

// The number of milliseconds between QR code scans.
const SCAN_PERIOD = 500;

@Component({
  selector: 'app-scan',
  templateUrl: './scan.ng.html',
  styleUrls: ['../app/common.css', './scan.component.css'],
})
export class ScanComponent implements OnInit {
  @ViewChild('video')
  public video: ElementRef;

  @ViewChild('canvas')
  public canvas: ElementRef;

  errorMessage: string = '';
  progressMessage: string = 'Waiting for QR code(s)';
  scanComplete: boolean = false;
  videoStartedSuccessfully = false;

  qrCodeValuePieces: string[] = [];
  qrCodeValuePieceSize = 0;

  scanStream: MediaStream | null = null;
  scanTimer: ReturnType<typeof setTimeout> | null = null;

  constructor(
    private ngZone: NgZone,
    private actionsSubmitter: ActionsSubmitter
  ) {}

  ngOnInit() {
    // If the user switched away from this tab, then the onRuntimeInitialized
    // attribute will already be set. No need to load OpenCV again. If it's not
    // loaded, however, we need to load it.
    if (!Module['onRuntimeInitialized']) {
      Module['onRuntimeInitialized'] = () => {
        // Since the WASM code doesn't know about the Angular zone, we force
        // it into the correct zone so that the UI gets updated properly.
        this.ngZone.run(() => {
          this.startScanning();
        });
      };
      // Now that we set up the hook, we can load OpenCV.
      this.loadOpenCv();
    } else {
      this.startScanning();
    }
  }

  ngOnDestroy() {
    clearInterval(this.scanTimer);

    // Explicitly stop the streams so that the camera isn't being locked
    // unnecessarily. I.e. other processes can use it too.
    if (this.scanStream) {
      this.scanStream.getTracks().forEach((track) => {
        track.stop();
      });
    }
  }

  public ngAfterViewInit() {
    // Start the video playback.
    // It would be nice to let the user select which camera gets used. For now,
    // we give the "environment" hint so that it faces away from the user.
    if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
      navigator.mediaDevices
        .getUserMedia({video: {facingMode: 'environment'}})
        .then(
          (stream) => {
            this.scanStream = stream;
            this.video.nativeElement.srcObject = stream;
            this.video.nativeElement.play();
            this.videoStartedSuccessfully = true;
          },
          (reason) => {
            this.progressMessage = '';
            this.errorMessage = `Failed to start video: ${reason}`;
          }
        );
    }
  }

  async scan() {
    if (!this.videoStartedSuccessfully) {
      return;
    }

    // Take a capture of the video stream. That capture can then be used by
    // OpenCV to perform the QR code detection. Due to my inexperience, I could
    // only make this code work if I size the (invisible) canvas to match the
    // video element. Otherwise, I'd get cropped images.
    // Can we stream the video directly into the canvas?
    const width = this.video.nativeElement.clientWidth;
    const height = this.video.nativeElement.clientHeight;
    this.canvas.nativeElement.width = width;
    this.canvas.nativeElement.height = height;
    this.canvas.nativeElement
      .getContext('2d')
      .drawImage(this.video.nativeElement, 0, 0, width, height);

    // Perform the QR code detection. We use the Aruco-variant of the detector
    // here because it appears to detect QR codes much more reliably than the
    // standard detector.
    let mat = cv.imread('canvas');
    let qrDecoder = new cv.QRCodeDetectorAruco();
    const result = qrDecoder.detectAndDecode(mat);
    mat.delete();

    // Handle the result.
    if (result) {
      await this.scanSuccessHandler(result);
    } else {
      await this.scanFailureHandler();
    }
  }

  async scanSuccessHandler(scanResult: string) {
    // Reverse the conversion and obtain the original Uint8Array. In other
    // words, undo the work in `scouting/www/entry/entry.component.ts`.
    const [indexStr, numPiecesStr, pieceSizeStr, splitPiece] = scanResult.split(
      '_',
      4
    );

    // If we didn't get enough data, then maybe we scanned some non-scouting
    // related QR code? Try to give a hint to the user.
    if (!indexStr || !numPiecesStr || !pieceSizeStr || !splitPiece) {
      this.progressMessage = '';
      this.errorMessage = `Couldn't find scouting data in the QR code.`;
      return;
    }

    const index = Number(indexStr);
    const numPieces = Number(numPiecesStr);
    const pieceSize = Number(pieceSizeStr);

    if (
      numPieces != this.qrCodeValuePieces.length ||
      pieceSize != this.qrCodeValuePieceSize
    ) {
      // The number of pieces or the piece size changed. We need to reset our accounting.
      this.qrCodeValuePieces = new Array<string>(numPieces);
      this.qrCodeValuePieceSize = pieceSize;
    }

    this.qrCodeValuePieces[index] = splitPiece;
    this.progressMessage = `Scanned QR code ${index + 1} out of ${
      this.qrCodeValuePieces.length
    }`;

    // Count up the number of missing pieces so we can give a progress update.
    let numMissingPieces = 0;
    for (const piece of this.qrCodeValuePieces) {
      if (!piece) {
        numMissingPieces++;
      }
    }
    if (numMissingPieces > 0) {
      this.progressMessage = `Waiting for ${numMissingPieces} out of ${this.qrCodeValuePieces.length} QR codes.`;
      this.errorMessage = '';
      return;
    }

    // Stop scanning now that we have all the pieces.
    this.progressMessage = 'Scanned all QR codes. Submitting.';
    this.scanComplete = true;
    clearInterval(this.scanTimer);

    const encodedData = this.qrCodeValuePieces.join('');
    const deflatedData = Uint8Array.from(atob(encodedData), (c) =>
      c.charCodeAt(0)
    );
    const actionBuffer = pako.inflate(deflatedData);

    const res = await this.actionsSubmitter.submit(actionBuffer);

    if (res.ok) {
      // We successfully submitted the data. Report success.
      this.progressMessage = 'Success!';
      this.errorMessage = '';
    } else {
      const resBuffer = await res.arrayBuffer();
      const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
      const parsedResponse = ErrorResponse.getRootAsErrorResponse(fbBuffer);

      const errorMessage = parsedResponse.errorMessage();
      this.progressMessage = '';
      this.errorMessage = `Submission failed with ${res.status} ${res.statusText}: "${errorMessage}"`;
    }
  }

  async scanFailureHandler() {
    this.progressMessage = '';
    this.errorMessage = 'Failed to scan!';
  }

  loadOpenCv() {
    // Make the browser load OpenCV.
    let body = <HTMLDivElement>document.body;
    let script = document.createElement('script');
    script.innerHTML = '';
    script.src = 'assets/opencv_4.9.0/opencv.js';
    script.async = false;
    script.defer = true;
    script.onerror = (error) => {
      this.progressMessage = '';
      if (typeof error === 'string') {
        this.errorMessage = `OpenCV failed to load: ${error}`;
      } else {
        this.errorMessage = 'OpenCV failed to load.';
      }
      // Since we use the onRuntimeInitialized property as a flag to see if we
      // need to perform loading, we need to delete the property. When the user
      // switches away from this tab and then switches back, we want to attempt
      // loading again.
      delete Module['onRuntimeInitialized'];
    };
    body.appendChild(script);
  }

  startScanning() {
    this.scanTimer = setInterval(() => {
      this.scan();
    }, SCAN_PERIOD);
  }
}
