/*eslint no-undef:0*/
/*eslint-env browser*/

"use strict";
var pagans = pagans || {};
/**
 * pagans.generateKey(params) create a public/private key compatible with apXtrib backend and store it in apx.data
 * pagans.detachedSignature(params) generate a detachedSignature for a Message that backend can check with the publicKey of the alias
 * pagans.checkdetachedSignature(params) check a detachedSignature for a Message (used on the backend as well)
 *
 *
 */

pagans.loadtpldata = () => {
  // adapte tpldata to template tpl
  // get list of tribes from nationchains/towns/idx/townId_all.json
  const datacreatepagan = { tribes: [] };

  apx.data.towns.idxtownId_all[apx.data.tpldata.setup.townId].tribes.forEach(
    (t) => {
      if (t == apx.data.tpldata.setup.tribeId) {
        datacreatepagan.tribes.push({ selected: true, tribeId: t });
      } else {
        datacreatepagan.tribes.push({ tribeId: t });
      }
    }
  );
  return datacreatepagan;
};

pagans.generateKey = async (alias, passphrase) => {
  /**
   * @param {string} alias a unique alias that identify an identity
   * @param {string} passphrase a string to cipher the publicKey (can be empty, less secure but simpler)
   * @return {publicKey,privateKey} with userIds = [{alias}]
   */
  const pgpparam = {
    type: "ecc", // Type of the key, defaults to ECC
    curve: "curve25519", // ECC curve name, defaults to curve25519
    userIDs: [{ alias: alias }], // you can pass multiple user IDs
    passphrase: passphrase, // protects the private key
    format: "armored", // output key format, defaults to 'armored' (other options: 'binary' or 'object')
  };
  const { privateKey, publicKey } = await openpgp.generateKey(pgpparam);
  // key start by '-----BEGIN PGP PRIVATE KEY BLOCK ... '
  // get liste  of alias:pubklickey await axios.get('api/v0/pagans')
  // check alias does not exist
  return { alias, privateKey, publicKey };
};
pagans.detachedSignature = async (pubK, privK, passphrase, message) => {
  /**
   * @pubK {string} a text public key
   * @privK {string} a test priv key
   * @passphrase {string} used to read privK
   * @message {string} message to sign
   * @Return a detached Signature of the message
   */
  const publicKey = await openpgp.readKey({ armoredKey: pubK });
  let privateKey;
  if (passphrase == "") {
    privateKey = await openpgp.readPrivateKey({ armoredKey: privK });
  } else {
    privateKey = await openpgp.decryptKey({
      privateKey: await openpgp.readPrivateKey({ armoredKey: privK }),
      passphrase,
    });
  }
  console.log(message);
  const msg = await openpgp.createMessage({ text: message });
  console.log(msg);
  const sig = await openpgp.sign({
    message: msg,
    signingKeys: privateKey,
    detached: true,
  });
  return btoa(sig);
};
pagans.authenticatedetachedSignature = async (
  alias,
  pubK,
  detachedSignature,
  message
) => {
  /**
   *  Check that alias (pubkey) signe a message
   *  @alias {string} alias link to the publicKey
   *  @pubK {string} publiKey text format
   *  @detachedSignature  {string} a detachedsignatured get from apx.detachedSignature
   *  @message {string} the message signed
   *  @return {boolean} true the message was signed by alias
   *                    false the message was not signed by alias
   */
  const publicKey = await openpgp.readKey({ armoredKey: pubK });
  const msg = await openpgp.createMessage({ text: message });
  const signature = await openpgp.readSignature({
    armoredSignature: atob(detachedSignature), // parse detached signature
  });
  const verificationResult = await openpgp.verify({
    msg, // Message object
    signature,
    verificationKeys: publicKey,
  });
  const { verified, keyID } = verificationResult.signatures[0];
  try {
    await verified; // throws on invalid signature
    console.log("Signed by key id " + keyID.toHex());
    return KeyId.toHex().alias == alias;
  } catch (e) {
    console.log("Signature could not be verified: " + e.message);
    return false;
  }
};
pagans.createIdentity = async (alias, passphrase = "") => {
  console.log(Object.keys(apx.data.pagans["idxalias_all"]));
  if (
    alias.length < 3 ||
    Object.keys(apx.data.pagans["idxalias_all"]).includes(alias)
  ) {
    alert("Please chose another alias");
    return;
  }
  const keys = await pagans.generateKey(alias, passphrase);
  for (let tag of ["inputalias", "inputpassphrase"]) {
    document.getElementById(tag).classList.add("disabled");
  }
  console.log(keys);
  document.getElementById("privatekey").setAttribute("key", keys.privateKey);
  document.getElementById("publickey").setAttribute("key", keys.publicKey);
  apx.data.tmp = keys; // to make it available for btn download
  document.getElementById("generatekeys").classList.add("d-none");
  document.getElementById("trustintribe").classList.remove("d-none");
  //document.getElementById("downloadkeys").classList.remove("d-none");
  document.getElementById("createId").classList.remove("d-none");
};

pagans.registerIdentity = async () => {
  const emailregex =
    /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  const data = {};
  data.alias = document.getElementById("inputalias").value;
  data.publickey = document.getElementById("publickey").getAttribute("key");

  if (document.getElementById("inputemailrecovery").value != "") {
    data.email = document.getElementById("inputemailrecovery").value;
  }
  if (data.email && !emailregex.test(data.email)) {
    alert("Check your email");
    return false;
  }
  var select = document.getElementById("trustedtribe");
  if (document.getElementById("trustedcheck").checked) {
    data.trustedtribe = select.options[select.selectedIndex].value;
    data.privatekey = document.getElementById("privatekey").getAttribute("key");
    data.passphrase = document.getElementById("inputpassphrase").value;
  }
  if (document.getElementById("trustedcheck").checked && !data.email) {
    alert("Please provide a valid email");
    return false;
  }
  console.log(data);
  //store and create authentification by signing 'alias_timestamp'
  /* const passp = data.passphrase ? data.passphrase : "";
  apx.data.auth = {
    alias: data.alias,
    publickey: data.publickey,
    privatekey: document.getElementById("privatekey").getAttribute("key"),
    passphrase: passp,
  };
  apx.data.headers.xalias = data.alias;
  apx.data.headers.xdays = dayjs().valueOf();
  apx.save();
  const msg = `${data.alias}_${apx.data.headers.xdays}`;
  apx.data.headers.xhash = await pagans.detachedSignature(
    apx.data.auth.publickey,
    apx.data.auth.privatekey,
    passp,
    msg
  );
  apx.save();*/
  await pagans.authentifyme(
    data.alias,
    data.passphrase,
    document.getElementById("privatekey").getAttribute("key"),
    document.getElementById("publickey").getAttribute("key")
  );
  console.log("header", apx.data.headers);
  axios
    .post("api/pagans", data, { headers: apx.data.headers })
    .then((reppagan) => {
      console.log(reppagan);
      if (reppagan.status==200)  {
        document.getElementById('downloadkeys').classList.remove('d-none');
        alert("Your identity is created, don't forget to download your key")
      }else{
        alert('Check the console an error appear');
      }
    })
    .catch((err) => {
      console.log("sorry", err);
    });
};

pagans.authentifyme = async (
  alias,
  passphrase,
  privatekey,
  publickeycreate
) => {
  /**
   * Set apx.data.auth with pub, priv, passphrase alias that allow authentification
   * set headers with xdays (timestamp) and xhash of message: {alias}_{timestamp} generate with pub & priv key
   *
   * @Param {key} publickeycreate  optional when alias does not exist
   */
  console.log(alias, passphrase);
  console.log(privatekey);
  const passp = passphrase ? passphrase : "";
  const publickey = publickeycreate
    ? publickeycreate
    : apx.data.pagans.idxalias_all[alias].publicKey;
  apx.data.auth = {
    alias: alias,
    publickey: publickey,
    privatekey: privatekey,
    passphrase: passp,
  };
  apx.data.headers.xalias = alias;
  apx.data.headers.xdays = dayjs().valueOf();
  apx.save();
  const msg = `${alias}_${apx.data.headers.xdays}`;

  apx.data.headers.xhash = await pagans.detachedSignature(
    apx.data.auth.publickey,
    apx.data.auth.privatekey,
    passp,
    msg
  );
  apx.save();
};

pagans.logout=()=>{
  delete apx.data.auth;
  delete apx.data.headers;
  apx.data.headers = apxlocal.headers; 
  apx.save();
  alert('delete apx.data.auth and reinit apx.data.header');
}