import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject, fromEvent, Subject } from 'rxjs';
import { filter, map, take, takeUntil, takeWhile } from 'rxjs/operators';
import { WindowRef } from './window-ref.service';
import { ScanRequestType } from './scan-request.type';

@Injectable({
  providedIn: 'root',
})
export class NativeContainerService {
  private wm: Observable<any>;
  public windowMessages = new Subject<any>();

  private webViewDetected = false;
  private webViewEventRecieved = false;
  private browserDetected = false;

  constructor(private windowRef: WindowRef) {
    this.defineWindowCallback();

    this.wm = fromEvent(this.windowRef.nativeWindow, 'message').pipe(
      map((e: MessageEvent) => {
        return e.data;
      })
    );

    this.wm.subscribe((data) => {
      if (data.status === 'INIT') {
        this.webViewEventRecieved = true;
      }
      this.windowMessages.next(data);
    });
  }

  public openScanner(scanRequestType: ScanRequestType) {
    const scanRequest = {
      [scanRequestType]: true,
    };

    this.sendMessage(scanRequest);

    return this.windowMessages.asObservable().pipe(map((message) => message as { status: string; data?: any }));
  }

  public sendMessage(message: any) {
    this.windowRef.nativeWindow.postMessage({ status: 'IN_PROGRESS', data: 'Scan Started' }, '*');

    try {
      // if (this.isUiWebview() && this.isUiWebview().isNative) {
      (this.windowRef.nativeWindow as any).webkit.messageHandlers.scanRequest.postMessage(message);
    } catch (error) {
      this.windowRef.nativeWindow.postMessage({ status: 'ERROR', data: 'Not a WebView' }, '*');
      this.windowRef.nativeWindow.postMessage(message, '*');
    }
  }

  public isUiWebview() {
    const navigator = this.windowRef.nativeWindow.navigator as Navigator;
    const standalone = (navigator as any).standalone,
      userAgent = navigator.userAgent.toLowerCase(),
      safari = /safari/.test(userAgent),
      ios = /iphone|ipod|ipad/.test(userAgent),
      chrome = /chrome/.test(userAgent) && /Google Inc/.test(navigator.vendor),
      crios = /crios/.test(userAgent);

    this.webViewDetected = ios && !standalone && !safari;
    this.browserDetected = !standalone && (safari || chrome) && !crios;
    return {
      isSafari: this.browserDetected,
      isNative: this.webViewDetected || this.webViewEventRecieved,
    };
  }

  public isIpadMini6() {
    const width = window.innerWidth > 0 ? window.innerWidth : screen.width;
    return width === 744;
  }

  private defineWindowCallback() {
    if (this.windowRef.nativeWindow['scanResults'] === undefined) {
      this.windowRef.nativeWindow['scanResults'] = (result) => window.postMessage(result, '*');
    }

    if (this.windowRef.nativeWindow['isRunningNative'] === undefined) {
      this.windowRef.nativeWindow['isRunningNative'] = (_) => window.postMessage({ status: 'INIT', data: 'Is a WebView' }, '*');
    }

    // Try sending ping request, to invoke the containers isRunningNative event
    try {
      (this.windowRef.nativeWindow as any).webkit.messageHandlers.scanRequest.postMessage('PING');
    } catch (error) {
      this.windowRef.nativeWindow.postMessage({ status: 'ERROR', data: 'Not a WebView' }, '*');
      this.windowRef.nativeWindow.postMessage('PING', '*');
    }
  }
}
