(async () => {

const lodePublicApi = {
  apiVersion: "0.1.0",
  name: "LodeWallet",
  icon: "data:image/png;base64,[encoded data, 26732 characters]",

  enable: async function enable() {
    const isEnabled = await __postMessage(["LodePublic_Enable", "stub"]);
    if (isEnabled) {
      return lodePrivateApi;
    }
  },
  isEnabled: async function isEnabled() {
    return await __postMessage(["LodePublic_IsEnabled", "stub"]);
  },
};

const lodePrivateApi = {
  getUsedAddresses: async function getUsedAddresses(paginate = null) {
    return await __postMessage(["LodePublic_GetUsedAddressesCBOR", paginate]);
  },
  getBalance: async function getBalance() {
    return await __postMessage(["LodePublic_GetBalanceCBOR", []]);
  },
  getNetworkId: async function getNetworkId() {
    return await __postMessage(["LodePublic_GetNetworkId", []]);
  },
  getUtxos: async function getUtxos(amount = null, paginate = null) {
    return await __postMessage(["LodePublic_GetUTxOCBOR", [amount, paginate]]);
  },
  signTx: async function signTx(tx, ps) {
    return await __postMessage(["LodePublic_SignTx", ["stub", tx]]);
  },
  submitTx: async function submitTx(tx) {
    return await __postMessage(["LodePublic_SubmitTx", tx]);
  },
  getUnusedAddresses: async () => [], /* No unused addresses in single address  */
  getChangeAddress: async () => {
    return await __postMessage(["LodePublic_GetChangeAddressCBOR", []]);
  },
  getRewardAddresses: async () => {
    return [await __postMessage(["LodePublic_GetRewardAddressCBOR", []])];
  },
  signData: async function signData(address, payload) {
    return await __postMessage(["LodePublic_SignData", ["stub", address, payload]]);
  },

  /* TODO: remove this; here for backwards compat */
  getRewardAddress: async () => {
    return await __postMessage(["LodePublic_GetRewardAddressCBOR", []]);
  },
  /* TODO: remove this; here for backwards compat */
  getCollateral: async function getCollateral() {
    return await __postMessage(["LodePublic_GetCollateralCBOR", []]);
  },
  /* TODO: remove this; here for backwards compat */
  onAccountChange: (cb) => {
    console.log("onAccountChange: NOT IMPLEMENTED")
    return { remove: () => console.log("REMOVE ACCOUNT CHANGE") }
  },
  /* TODO: remove this; here for backwards compat */
  onNetworkChange: (cb) => {
    console.log("onNetworkChange: NOT IMPLEMENTED")
    return { remove: () => console.log("REMOVE NETWORK CHANGE") }
  },

  experimental: {
    getCollateral: async function getCollateral() {
      return await __postMessage(["LodePublic_GetCollateralCBOR", []]);
    },
    on: (eventName, cb) => {
      console.log(".on not supported")
    },
    off: (eventName, cb) => {
      console.log(".off not supported")
    }
  }
};

const VERBOSE = false;
function __log(msg) {
  if (VERBOSE) console.log(msg)
};

function __notImplemented(name) {
  console.log("============== NOT IMPLEMENTED =====================" + name);
  return new Promise((res, rej) => rej("NOT IMPLEMENTED: "+name))
}

function __postMessage(msg) {
  return new Promise((res, rej) => {
    const requestId = Math.random().toString(36).substr(2, 9);
    window.addEventListener('message', function responseHandler(e) {
      __log("INJECTED RECEIVE MESSAGE: " + (e.data || ""));
      __log(e);
      const response = e.data;
      if (
        typeof response === 'undefined' ||
        response === null ||
        response.id === null ||
        response.id !== requestId ||
        response._sourceIsExtension !== true
      )
        return;
      __log("INJECTED REMOVE MSG LISTENER");
      window.removeEventListener('message', responseHandler);
      if (response.error) rej(response.error);
      else res(response.response);
    });
    __log("INJECTED POST MESSAGE: " + (msg || ""));
    if (typeof AndroidBridge !== 'undefined') {
      AndroidBridge.sendDomMessage(JSON.stringify({ id: requestId, target: 'lode', data: msg }));
    } else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.iOSBridge) { /* iOS */
      console.log("WEBKIT BROWSER FOUND");
      window.webkit.messageHandlers.iOSBridge.postMessage(JSON.stringify({ id: requestId, target: 'lode', data: msg }));
    } else {
      window.postMessage({ id: requestId, target: 'lode', data: msg });
    }
  });
}

// Some messages are sent by the extension without a prompt
// We listen for those here. Currently only used to check
// the wallet identity again.
window.addEventListener('message', async e => {
  __log("PROMPT RECEIVE MESSAGE: " + (e.data || ""));
  __log(e);
  const response = e.data;
  if (
    typeof response === 'undefined' ||
    response === null ||
    response.id !== null ||
    response.prompt === null ||
    response.error !== null ||
    response._sourceIsExtension !== true
  ) return;
  await setWalletIdentity();
});

const namiBackwardsCompat = Object.assign({}, lodePublicApi, lodePrivateApi);

const setWalletIdentity = async () => {
  const rsp = await __postMessage(["LodePublic_GetWalletIdentity", []]);
  __log(rsp)
  switch(rsp) {
    case 'AccountWalletIdentity_LodeWallet':
      window.cardano = Object.assign(
        {},
        window.cardano,
        { LodeWallet: lodePublicApi }
      );
      break;
    case 'AccountWalletIdentity_Nami':
      if(window.cardano) delete window.cardano.LodeWallet;
      window.cardano = Object.assign(
        {},
        window.cardano,
        namiBackwardsCompat,
        { nami: lodePublicApi }
      );
      break;
    default:
      __log("UNKNOWN WALLET IDENTITY RESPONSE");
      window.cardano = Object.assign(
        {},
        window.cardano,
        { LodeWallet: lodePublicApi }
      );
      break;
  }
}

await setWalletIdentity()

})();
