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

import { assert } from "jsr:/@std/assert@^0.224.0/assert";
import { assertPath } from "../_common/assert_path.ts";
import { isPathSeparator } from "./_util.ts";
import { normalize } from "./normalize.ts";

/**
 * Join all given a sequence of `paths`,then normalizes the resulting path.
 * @param paths to be joined and normalized
 */
export function join(...paths: string[]): string {
  if (paths.length === 0) return ".";

  let joined: string | undefined;
  let firstPart: string | null = null;
  for (let i = 0; i < paths.length; ++i) {
    const path = paths[i]!;
    assertPath(path);
    if (path.length > 0) {
      if (joined === undefined) joined = firstPart = path;
      else joined += `\\${path}`;
    }
  }

  if (joined === undefined) return ".";

  // Make sure that the joined path doesn't start with two slashes, because
  // normalize() will mistake it for an UNC path then.
  //
  // This step is skipped when it is very clear that the user actually
  // intended to point at an UNC path. This is assumed when the first
  // non-empty string arguments starts with exactly two slashes followed by
  // at least one more non-slash character.
  //
  // Note that for normalize() to treat a path as an UNC path it needs to
  // have at least 2 components, so we don't filter for that here.
  // This means that the user can use join to construct UNC paths from
  // a server name and a share name; for example:
  //   path.join('//server', 'share') -> '\\\\server\\share\\')
  let needsReplace = true;
  let slashCount = 0;
  assert(firstPart !== null);
  if (isPathSeparator(firstPart.charCodeAt(0))) {
    ++slashCount;
    const firstLen = firstPart.length;
    if (firstLen > 1) {
      if (isPathSeparator(firstPart.charCodeAt(1))) {
        ++slashCount;
        if (firstLen > 2) {
          if (isPathSeparator(firstPart.charCodeAt(2))) ++slashCount;
          else {
            // We matched a UNC path in the first part
            needsReplace = false;
          }
        }
      }
    }
  }
  if (needsReplace) {
    // Find any more consecutive slashes we need to replace
    for (; slashCount < joined.length; ++slashCount) {
      if (!isPathSeparator(joined.charCodeAt(slashCount))) break;
    }

    // Replace the slashes if needed
    if (slashCount >= 2) joined = `\\${joined.slice(slashCount)}`;
  }

  return normalize(joined);
}

// denoCacheMetadata={"headers":{"access-control-expose-headers":"*","content-type":"text/typescript","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';","cross-origin-resource-policy":"cross-origin","x-content-type-options":"nosniff","server":"cloudflare","etag":"\"c03bb90f2bc4a46d0dc82373463ca50b\"","cf-ray":"a223e6583bbe7db6-LAX","date":"Tue, 28 Jul 2026 12:31:15 GMT","age":"3893595","accept-ranges":"bytes","report-to":"{\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://a.nel.cloudflare.com/report/v4?s=He0%2Fd1yXXjJr8rXBry%2FzHaLnYbkN3pX7opIbRGL89VBYFHyQe4YajfB8DDvTwAFhT%2BICsXbaeexHl3WI6fKin3NxUr0Ll7QGwM1W2V8cz2ZIKnaDiAS1QT0%3D\"}]}","cf-cache-status":"HIT","x-jsr-backend":"modules","content-length":"2483","access-control-allow-origin":"*","x-robots-tag":"noindex","nel":"{\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}","alt-svc":"h3=\":443\"; ma=86400","cache-control":"public, max-age=31536000, immutable","set-cookie":"__cf_bm=jFEWzeef1dkqD1rkLWFU1qz3hwww3dvs_AuOiLls4aQ-1785241875.2384522-1.0.1.1-2WKdKRIg9WlccsgU.V3YyGmxFqhWhsZZ7khWTaI9nHMMn7tT9S1uNMYFH_zImvgI9ooCKoZBPNx0mw9A8.JS6dS5.djiQY2Gja9SIHMwSc6fjmrNrj6ZSykzyn39iUbY; HttpOnly; SameSite=None; Secure; Path=/; Domain=jsr.io; Expires=Tue, 28 Jul 2026 13:01:15 GMT","vary":"Origin"},"url":"https://jsr.io/@std/path/0.224.0/windows/join.ts","time":1785241875}