import * as ipaddr from "ipaddr.js"

async function handler(event) {
  // Get the request from the client.
  const req = event.request

  // Parse the client IP address.
  let address = ipaddr.parse(event.client.address)
  
  // If if IP address is v6...
  if (address.kind() === "ipv6") {
    console.log("Received a request via IPv6")

    // Calculate a SHA-1 hash of the client IP address.
    const encoder = new TextEncoder()
    const data = encoder.encode(address)
    const hash = await crypto.subtle.digest("SHA-1", data)
    const hashArray = Array.from(new Uint8Array(hash))
    

    // Construct an IPv4 address from the first 4 bytes of the hash.
    address = ipaddr.fromByteArray([0xf0 | hashArray[0], hashArray[1], hashArray[2], hashArray[3]])

    console.log("Constructed IPv4 address " + address.toString())
  } else {
    console.log("Received a request via IPv4")
  }

  // Add the IP address as a header.
  req.headers.set("x-ipv4", address.toString())

  // Forward the request to the origin.
  return fetch(req, {
    backend: "origin_0",
  })
}

addEventListener("fetch", (event) => event.respondWith(handler(event)))

// https://gist.github.com/artjomb/7ef1ee574a411ba0dd1933c1ef4690d1
function wordToByteArray(word, length) {
  let ba = [],
    xFF = 0xff
  if (length > 0) ba.push(word >>> 24)
  if (length > 1) ba.push((word >>> 16) & xFF)
  if (length > 2) ba.push((word >>> 8) & xFF)
  if (length > 3) ba.push(word & xFF)

  return ba
}

function wordArrayToByteArray(wordArray, length) {
  if (wordArray.hasOwnProperty("sigBytes") && wordArray.hasOwnProperty("words")) {
    length = wordArray.sigBytes
    wordArray = wordArray.words
  }

  let result = [],
    bytes,
    i = 0
  while (length > 0) {
    bytes = wordToByteArray(wordArray[i], Math.min(4, length))
    length -= bytes.length
    result.push(bytes)
    i++
  }
  return [].concat.apply([], result)
}