/**
 * Function will replace the middle of the string with ellipsis if length greater then
 * offset value
 * @param str string to shorten
 * @param offset of how many chars to keep in the beginning and the end
 * eg. 3 will keep first 3 chars and last 3 chars between the dots
 */
export const shorten = (str: string, offset = 9) => {
  // return original string if it is not long enough
  if (str.length < offset * 2 + 4) return str

  return `${str.slice(0, offset)}…${str.slice(str.length - offset, str.length)}`
}

export const stringToHex = (str: string) => {
  // Convert the string to an array of UTF-16 code units using the spread operator
  const codeUnits = [...str]

  // Map each code unit to its hexadecimal representation
  const hexChars = codeUnits.map((codeUnit) => {
    // Convert the code unit to its hexadecimal representation with leading zeros
    const hex = codeUnit.charCodeAt(0).toString(16).padStart(2, '0')
    return hex
  })

  // Join the hexadecimal characters into a single string
  const hexString = hexChars.join('')

  // Return the resulting hexadecimal string
  return hexString
}

export const hexToString = (hex: string) => {
  // Split the hex string into pairs of two characters
  const pairs = hex.match(/.{1,2}/g) || []

  // Convert each pair from hexadecimal to its decimal equivalent,
  // then convert each decimal value to its character representation
  const chars = pairs.map((pair) => String.fromCharCode(parseInt(pair, 16)))

  // Join the resulting characters into a single string
  return chars.join('')
}

// Function to convert a Uint8Array to a hexadecimal string
export const uint8ArrayToHexString = (uint8Array: Uint8Array) => {
  // Convert each byte in the Uint8Array to a hexadecimal string,
  // pad it with leading zeros if necessary, and join the results
  return Array.from(uint8Array)
    .map((byte) => byte.toString(16).padStart(2, '0')) // Convert byte to hexadecimal string
    .join('') // Join all hexadecimal strings
}

// Function to convert a hexadecimal string to a Uint8Array
export const hexStringToUint8Array = (hexString: string) => {
  // Create a new Uint8Array with half the length of the hex string
  const uint8Array = new Uint8Array(hexString.length / 2)
  // Iterate over pairs of characters in the hex string
  for (let i = 0; i < hexString.length; i += 2) {
    // Parse the pair of characters as a hexadecimal value and store it in the Uint8Array
    uint8Array[i / 2] = parseInt(hexString.substr(i, 2), 16)
  }
  // Return the resulting Uint8Array
  return uint8Array
}

/**
 * Parses JSON content asynchronously.
 * @param content The JSON content to parse.
 * @returns A Promise that resolves to the parsed JSON object.
 */
export const parseJson = <T>(content: string): Promise<T> => {
  return new Promise((resolve, reject) => {
    try {
      // Attempt to parse the JSON content
      const json = JSON.parse(content) as T
      // Resolve the promise with the parsed JSON object
      resolve(json)
    } catch (error) {
      // If parsing fails, reject the promise with the error
      reject(error)
    }
  })
}

/**
 * Capitalizes the first character in the string
 * @param str string to modify
 * @returns modified string
 */
export const capitalizeFirstLetter = (str: string) =>
  str.charAt(0).toUpperCase() + str.slice(1).toLowerCase()

export const formatTimestamp = (timestamp: number) => {
  const date = new Date(timestamp)

  // Extract date parts
  const day = date.getDate().toString().padStart(2, '0')
  const month = date.toLocaleString('default', { month: 'short' })
  const year = date.getFullYear()

  // Format time parts
  const hours = date.getHours()
  const minutes = date.getMinutes().toString().padStart(2, '0')
  const ampm = hours >= 12 ? 'PM' : 'AM'
  const formattedHours = (hours % 12 || 12).toString().padStart(2, '0')

  // Combine parts into the desired format
  return `${day} ${month} ${year} ${formattedHours}:${minutes} ${ampm}`
}

/**
 * Removes the leading slash from a given string if it exists.
 *
 * @param str - The string from which to remove the leading slash.
 * @returns The string without the leading slash.
 */
export const removeLeadingSlash = (str: string): string => {
  // Check if the string starts with a leading slash
  if (str.startsWith('/')) {
    // If it does, return the string without the leading slash
    return str.slice(1)
  }
  // If it doesn't, return the original string
  return str
}
