//  Copyright (c) 2024 Huawei Technologies Co., Ltd.
//  openUBMC is licensed under Mulan PSL v2.
//  You can use this software according to the terms and conditions of the Mulan PSL v2.
//  You may obtain a copy of Mulan PSL v2 at:
//        #  http://license.coscl.org.cn/MulanPSL2
//  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
//  EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
//  MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
//  See the Mulan PSL v2 for more details.
function stringToArrayBuffer(str: string): ArrayBuffer {
  const encoder = new TextEncoder();
  const uint8Array = encoder.encode(str);
  return uint8Array.buffer;
}

/**
 * sting字符串转ArrayBuffer
 * @param str
 * @returns
 */
function strToArrayBuffer(str: string): ArrayBuffer {
  const buffer = new ArrayBuffer(str.length);
  const viewArray = new Uint8Array(buffer);
  let i = 0;
  while (i < str.length) {
    viewArray[i] = str.charCodeAt(i);
    i++;
  }
  return buffer;
}

/**
 * 通过pem格式的公钥/私钥生成CryptoKey对象
 * @param pem pem字符串
 * @param [hash] hash算法，默认SHA-512。注意安全要求不可使用SHA-1
 * @param [isPublicKey] 是否为公钥
 * @returns CryptoKey对象
 */
async function importRsaKey(pem: any, hash = 'SHA-512', isPublicKey = true): Promise<CryptoKey> {
  // 获取头尾部分的长度，用于字符串截取
  const headerStr = `-----BEGIN ${isPublicKey ? `PUBLIC` : `PRIVATE`} KEY-----`;
  const footerStr = `-----END ${isPublicKey ? `PUBLIC` : `PRIVATE`} KEY-----`;
  // 判断是否有换行符\n，兼容处理
  const headerLen = headerStr.length;
  let footerLen = footerStr.length;
  if (pem[pem.length - footerStr.length] === '\n') {
    footerLen++;
  }
  if (pem[pem.length - 1] === '\n') {
    footerLen++;
  }
  // 截取 PEM 密钥字符串的中间部分
  const base64Contents = pem.substring(headerLen, pem.length - footerLen);
  // base64转为二进制字符串
  const pemStr = window.atob(base64Contents);
  // 字符串转换为ArrayBuffer
  const pemBuffer = strToArrayBuffer(pemStr);
  // 生成CryptoKey对象
  return await window.crypto.subtle.importKey(
      isPublicKey ? 'spki' : 'pkcs8',
      pemBuffer,
      {
        name: 'RSA-OAEP',
        hash,
      },
      true,
      [isPublicKey ? 'encrypt' : 'decrypt']
  );
}

/**
 * 通过pem格式的公钥生成CryptoKey对象
 * @param pem pem公钥字符串
 * @param [hash] hash算法，默认SHA-512。注意安全要求不可使用SHA-1
 * @returns CryptoKey对象
 */
export async function importRsaPublicKey(pem: string, hash = 'SHA-1'): Promise<CryptoKey> {
  return await importRsaKey(pem, hash, true);
}

/**
 * Rsas encrypt
 * @param srcStr 待加密的字符串
 * @param publicKey 公钥，需要先使用importRsaPublicKey函数导入生成公钥对象
 * @returns encrypt
 */
export async function rsaEncrypt(srcStr: string, publicKey: CryptoKey): Promise<string> {
  // 将源字符串转为Uint8Array
  const encodedStr = stringToArrayBuffer(srcStr);
  // 使用公钥加密
  return await crypto.subtle.encrypt(
      {
        name: 'RSA-OAEP',
      },
      publicKey,
      encodedStr
  );
}
export async function rsaDecrypt(srcStr: ArrayBuffer, privateKey: CryptoKey): Promise<string> {
  // 使用私钥解密
  return await crypto.subtle.decrypt(
      {
        name: 'RSA-OAEP',
      },
      privateKey,
      srcStr
  );
}

/**
 * ArrayBuffer转string字符串
 * @returns
 * @param arrayBuffer
 */
export function arrayBufferToHexStr(arrayBuffer: any): string {
  if (typeof arrayBuffer !== 'object' || arrayBuffer === null || typeof arrayBuffer.byteLength !== 'number') {
    throw new TypeError('Expected input to be an ArrayBuffer');
  }

  const view = new Uint8Array(arrayBuffer);
  let result = '';
  let value;

  view.forEach(e => {
    value = e.toString(16);
    result += value.length === 1 ? `0${value}` : value;
  });

  return result;
}