import type Transport from "@ledgerhq/hw-transport";
import bippath from "bip32-path";
import { MAX_SCRIPT_BLOCK } from "./constants";
export async function signMessage(
  transport: Transport,
  {
    path,
    messageHex,
  }: {
    path: string;
    messageHex: string;
  },
): Promise<{
  v: number;
  r: string;
  s: string;
}> {
  const paths = bippath.fromString(path).toPathArray();
  const message = Buffer.from(messageHex, "hex");
  let offset = 0;

  while (offset !== message.length) {
    const maxChunkSize =
      offset === 0 ? MAX_SCRIPT_BLOCK - 1 - paths.length * 4 - 4 : MAX_SCRIPT_BLOCK;
    const chunkSize =
      offset + maxChunkSize > message.length ? message.length - offset : maxChunkSize;
    const buffer = Buffer.alloc(offset === 0 ? 1 + paths.length * 4 + 2 + chunkSize : chunkSize);

    if (offset === 0) {
      buffer[0] = paths.length;
      paths.forEach((element, index) => {
        buffer.writeUInt32BE(element, 1 + 4 * index);
      });
      buffer.writeUInt16BE(message.length, 1 + 4 * paths.length);
      message.copy(buffer, 1 + 4 * paths.length + 2, offset, offset + chunkSize);
    } else {
      message.copy(buffer, 0, offset, offset + chunkSize);
    }

    await transport.send(0xe0, 0x4e, 0x00, offset === 0 ? 0x01 : 0x80, buffer);
    offset += chunkSize;
  }

  const res = await transport.send(0xe0, 0x4e, 0x80, 0x00, Buffer.from([0x00]));
  const v = res[0] - 0x30;
  let r: Buffer | string = res.slice(4, 4 + res[3]);

  if (r[0] === 0) {
    r = r.slice(1);
  }

  r = r.toString("hex");
  offset = 4 + res[3] + 2;
  let s: Buffer | string = res.slice(offset, offset + res[offset - 1]);

  if (s[0] === 0) {
    s = s.slice(1);
  }

  s = s.toString("hex");
  return {
    v,
    r,
    s,
  };
}
