/*
 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,
  keepAlive: (cb: VoidFunction) => cb(),
  findTalerUriInActiveTab: async () => undefined,
  containsTalerHeaderListener: () => {
    return true;
  },
  getPermissionsApi: () => ({
    addPermissionsListener: () => undefined,
    containsHostPermissions: async () => true,
    removeHostPermissions: async () => false,
    requestHostPermissions: 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;