/*
 This file is part of GNU Taler
 (C) 2021 Taler Systems S.A.
 GNU Taler is free software; you can redistribute it and/or modify it under the
 terms of the GNU General Public License as published by the Free Software
 Foundation; either version 3, or (at your option) any later version.
 GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 You should have received a copy of the GNU General Public License along with
 GNU Taler; see the file COPYING.  If not, see 
 */
import { CoreApiResponse } from "@gnu-taler/taler-util";
import { MessageFromBackend, PlatformAPI } from "./api.js";
const frames = ["popup", "wallet"]
const api: PlatformAPI = ({
  isFirefox: () => false,
  findTalerUriInActiveTab: async () => undefined,
  getPermissionsApi: () => ({
    addPermissionsListener: () => undefined, contains: async () => true, remove: async () => false, request: async () => false
  }),
  getWalletVersion: () => ({
    version: 'none'
  }),
  notifyWhenAppIsReady: (fn: () => void) => {
    let total = frames.length
    function waitAndNotify(): void {
      total--
      if (total < 1) {
        console.log('done')
        fn()
      }
    }
    frames.forEach(f => {
      const theFrame = window.frames[f as any]
      if (theFrame.location.href === 'about:blank') {
        waitAndNotify()
      } else {
        theFrame.addEventListener("load", waitAndNotify)
      }
    })
  },
  openWalletPage: (page: string) => {
    window.frames['wallet' as any].location = `/wallet.html#${page}`
  },
  openWalletPageFromPopup: (page: string) => {
    window.parent.frames['wallet' as any].location = `/wallet.html#${page}`
    window.location.href = "about:blank"
  },
  openWalletURIFromPopup: (page: string) => {
    alert('openWalletURIFromPopup not implemented yet')
  },
  redirectTabToWalletPage: (tabId: number, page: string) => {
    alert('redirectTabToWalletPage not implemented yet')
  },
  registerAllIncomingConnections: () => undefined,
  registerOnInstalled: (fn: () => void) => undefined,
  registerReloadOnNewVersion: () => undefined,
  registerTalerHeaderListener: () => undefined,
  useServiceWorkerAsBackgroundProcess: () => false,
  listenToAllChannels: (fn: (m: any, s: any, c: (r: CoreApiResponse) => void) => void) => {
    window.addEventListener("message", (event: MessageEvent) => {
      if (event.data.type !== 'command') return
      const sender = event.data.header.replyMe
      fn(event.data.body, sender, (resp: CoreApiResponse) => {
        if (event.source) {
          const msg: IframeMessageResponse = {
            type: "response",
            header: { responseId: sender },
            body: resp
          }
          window.parent.postMessage(msg)
        }
      })
    })
  },
  sendMessageToAllChannels: (message: MessageFromBackend) => {
    Array.from(window.frames).forEach(w => {
      try {
        w.postMessage({
          header: {}, body: message
        });
      } catch (e) {
        console.error(e)
      }
    })
  },
  listenToWalletBackground: (onNewMessage: (m: MessageFromBackend) => void) => {
    function listener(event: MessageEvent): void {
      if (event.data.type !== 'notification') return
      onNewMessage(event.data.body)
    }
    window.parent.addEventListener("message", listener)
    return () => {
      window.parent.removeEventListener("message", listener)
    }
  },
  sendMessageToWalletBackground: async (operation: string, payload: any) => {
    const replyMe = `reply-${Math.floor(Math.random() * 100000)}`
    const message: IframeMessageCommand = {
      type: 'command',
      header: { replyMe },
      body: { operation, payload, id: "(none)" }
    }
    window.parent.postMessage(message)
    return new Promise((res, rej) => {
      function listener(event: MessageEvent): void {
        if (event.data.type !== "response" || event.data.header.responseId !== replyMe) {
          return
        }
        res(event.data.body)
        window.parent.removeEventListener("message", listener)
      }
      window.parent.addEventListener("message", listener, {
      })
    })
  },
})
type IframeMessageType = IframeMessageNotification | IframeMessageResponse | IframeMessageCommand;
interface IframeMessageNotification {
  type: "notification";
  header: Record,
  body: MessageFromBackend
}
interface IframeMessageResponse {
  type: "response";
  header: {
    responseId: string;
  },
  body: CoreApiResponse
}
interface IframeMessageCommand {
  type: "command";
  header: {
    replyMe: string;
  },
  body: {
    operation: any, id: string, payload: any
  }
}
export default api;