// Ported from js-yaml v3.13.1:
// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { Type } from "../type.ts";
import type { Any } from "../_utils.ts";

// [ 64, 65, 66 ] -> [ padding, CR, LF ]
const BASE64_MAP =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";

function resolveYamlBinary(data: Any): boolean {
  if (data === null) return false;

  let code: number;
  let bitlen = 0;
  const max = data.length;
  const map = BASE64_MAP;

  // Convert one by one.
  for (let idx = 0; idx < max; idx++) {
    code = map.indexOf(data.charAt(idx));

    // Skip CR/LF
    if (code > 64) continue;

    // Fail on illegal characters
    if (code < 0) return false;

    bitlen += 6;
  }

  // If there are any bits left, source was corrupted
  return bitlen % 8 === 0;
}

function constructYamlBinary(data: string): Uint8Array {
  // remove CR/LF & padding to simplify scan
  const input = data.replace(/[\r\n=]/g, "");
  const max = input.length;
  const map = BASE64_MAP;

  // Collect by 6*4 bits (3 bytes)

  const result = [];
  let bits = 0;
  for (let idx = 0; idx < max; idx++) {
    if (idx % 4 === 0 && idx) {
      result.push((bits >> 16) & 0xff);
      result.push((bits >> 8) & 0xff);
      result.push(bits & 0xff);
    }

    bits = (bits << 6) | map.indexOf(input.charAt(idx));
  }

  // Dump tail

  const tailbits = (max % 4) * 6;

  if (tailbits === 0) {
    result.push((bits >> 16) & 0xff);
    result.push((bits >> 8) & 0xff);
    result.push(bits & 0xff);
  } else if (tailbits === 18) {
    result.push((bits >> 10) & 0xff);
    result.push((bits >> 2) & 0xff);
  } else if (tailbits === 12) {
    result.push((bits >> 4) & 0xff);
  }

  return new Uint8Array(result);
}

function representYamlBinary(object: Uint8Array): string {
  const max = object.length;
  const map = BASE64_MAP;

  // Convert every three bytes to 4 ASCII characters.

  let result = "";
  let bits = 0;
  for (let idx = 0; idx < max; idx++) {
    if (idx % 3 === 0 && idx) {
      result += map[(bits >> 18) & 0x3f];
      result += map[(bits >> 12) & 0x3f];
      result += map[(bits >> 6) & 0x3f];
      result += map[bits & 0x3f];
    }

    bits = (bits << 8) + object[idx]!;
  }

  // Dump tail

  const tail = max % 3;

  if (tail === 0) {
    result += map[(bits >> 18) & 0x3f];
    result += map[(bits >> 12) & 0x3f];
    result += map[(bits >> 6) & 0x3f];
    result += map[bits & 0x3f];
  } else if (tail === 2) {
    result += map[(bits >> 10) & 0x3f];
    result += map[(bits >> 4) & 0x3f];
    result += map[(bits << 2) & 0x3f];
    result += map[64];
  } else if (tail === 1) {
    result += map[(bits >> 2) & 0x3f];
    result += map[(bits << 4) & 0x3f];
    result += map[64];
    result += map[64];
  }

  return result;
}

function isBinary(obj: Any): obj is Uint8Array {
  return obj instanceof Uint8Array;
}

export const binary = new Type("tag:yaml.org,2002:binary", {
  construct: constructYamlBinary,
  kind: "scalar",
  predicate: isBinary,
  represent: representYamlBinary,
  resolve: resolveYamlBinary,
});

// denoCacheMetadata={"headers":{"date":"Tue, 28 Jul 2026 12:31:15 GMT","content-length":"3246","cf-ray":"a223e6589cdf7db6-LAX","content-type":"text/typescript","etag":"\"ec4ddb109019d329ad08b16c82b5041b\"","vary":"Origin","cross-origin-resource-policy":"cross-origin","set-cookie":"__cf_bm=12wMIY98xGKM0X91JUzZ2WV001pTWvmP_F1BwjR1kUo-1785241875.2966893-1.0.1.1-X6ypkZa4ZOu0AO8X_v2ODwB3V24dhRODMjQ0vYpXWz4yYsCVjPkOsiWGTkO.16aIcZ3w8d_udeCTrlnXuDRsVFpod73Sy2OHqgnfDmroUnbmeFXeIGi0g_vnSidjk0Cg; HttpOnly; SameSite=None; Secure; Path=/; Domain=jsr.io; Expires=Tue, 28 Jul 2026 13:01:15 GMT","accept-ranges":"bytes","server":"cloudflare","age":"46611","x-robots-tag":"noindex","report-to":"{\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://a.nel.cloudflare.com/report/v4?s=6XDTUp53PEkVZ%2FGgdTblhd0%2FVjPDlcupKrhjhJgggFg%2FGWapV3t5FqfvTMatBJAgjUV6xMpk3ZTq%2B3DEpkls6Wwbs5HqNd4BicXucCeK1TQ3EFoQIsphDq0%3D\"}]}","alt-svc":"h3=\":443\"; ma=86400","x-content-type-options":"nosniff","cf-cache-status":"HIT","cache-control":"public, max-age=31536000, immutable","content-security-policy":"default-src 'none'; script-src 'none'; style-src 'none'; img-src 'none'; font-src 'none'; connect-src 'none'; frame-src 'none'; object-src 'none'; frame-ancestors 'none'; sandbox; form-action 'none';","x-jsr-backend":"modules","nel":"{\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}","access-control-allow-origin":"*","access-control-expose-headers":"*"},"url":"https://jsr.io/@std/yaml/0.224.3/_type/binary.ts","time":1785241875}