// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.

/**
 * Returns the index of the last occurrence of the needle array in the source
 * array, or -1 if it is not present.
 *
 * The complexity of this function is `O(source.length * needle.length)`.
 *
 * @param source Source array to check.
 * @param needle Needle array to check for.
 * @param start Start index in the source array to begin the search. Defaults to
 * the end of the array.
 * @returns Index of the last occurrence of the needle array in the source
 * array, or -1 if it is not present.
 *
 * @example Basic usage
 * ```ts
 * import { lastIndexOfNeedle } from "@std/bytes/last-index-of-needle";
 *
 * const source = new Uint8Array([0, 1, 2, 1, 2, 1, 2, 3]);
 * const needle = new Uint8Array([1, 2]);
 * const notNeedle = new Uint8Array([5, 0]);
 *
 * lastIndexOfNeedle(source, needle); // 5
 * lastIndexOfNeedle(source, notNeedle); // -1
 * ```
 *
 * @example Start index
 * ```ts
 * import { lastIndexOfNeedle } from "@std/bytes/last-index-of-needle";
 *
 * const source = new Uint8Array([0, 1, 2, 1, 2, 1, 2, 3]);
 * const needle = new Uint8Array([1, 2]);
 *
 * lastIndexOfNeedle(source, needle, 2); // 1
 * lastIndexOfNeedle(source, needle, 6); // 3
 * ```
 * Defining a start index will begin the search at the specified index in the
 * source array.
 */
export function lastIndexOfNeedle(
  source: Uint8Array,
  needle: Uint8Array,
  start: number = source.length - 1,
): number {
  if (start < 0) {
    return -1;
  }
  if (start >= source.length) {
    start = source.length - 1;
  }
  const e = needle[needle.length - 1];
  for (let i = start; i >= 0; i--) {
    if (source[i] !== e) continue;
    let matched = 1;
    let j = i;
    while (
      matched < needle.length &&
      source[--j] === needle[needle.length - 1 - (i - j)]
    ) {
      matched++;
    }
    if (matched === needle.length) {
      return i - needle.length + 1;
    }
  }
  return -1;
}

// denoCacheMetadata={"headers":{"access-control-allow-origin":"*","content-length":"2001","content-type":"text/typescript","age":"36641","access-control-expose-headers":"*","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-content-type-options":"nosniff","etag":"\"1b5d75d366db624c9c391784af405be8\"","x-robots-tag":"noindex","set-cookie":"__cf_bm=OOTZNLMJFoG0btJko7cNqp6RLoFh00mk4.zMyJJrtk0-1785241874.9466457-1.0.1.1-RIHCzKYecO2SVT.swVMEIQmY2c_I_hQRX9QSUyEG.H_jhA8EC0DY55jKo3OUM44i.si_mB3dFxPuc.dEHjDva7IOue8IdiEXJtM509xW5gjnNKTq7ZVnLgZ0IhVjVQH3; HttpOnly; SameSite=None; Secure; Path=/; Domain=jsr.io; Expires=Tue, 28 Jul 2026 13:01:14 GMT","server":"cloudflare","cf-ray":"a223e6564ed37db6-LAX","report-to":"{\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://a.nel.cloudflare.com/report/v4?s=RgVrBWJhexkZSlbcsvQbwgR%2BB9KLoWVkPDBGLzwAf4g6%2Fi6isB%2FIIzmu6jKjJIDijf%2BHBgTXDvqsNYez5916nRSwpnDd6cUTVaHbnowDsexFysy6I1qvpGY%3D\"}]}","nel":"{\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}","alt-svc":"h3=\":443\"; ma=86400","vary":"Origin","cf-cache-status":"HIT","cache-control":"public, max-age=31536000, immutable","x-jsr-backend":"modules","date":"Tue, 28 Jul 2026 12:31:14 GMT","accept-ranges":"bytes","cross-origin-resource-policy":"cross-origin"},"url":"https://jsr.io/@std/bytes/0.224.0/last_index_of_needle.ts","time":1785241874}