import { dollar, type QRL } from './qrl.public';

// <docs markdown="../../readme.md#implicit$FirstArg">
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
// (edit ../../readme.md#implicit$FirstArg instead and run `pnpm docs.sync`)
/**
 * Create a `____$(...)` convenience method from `___(...)`.
 *
 * It is very common for functions to take a lazy-loadable resource as a first argument. For this
 * reason, the Qwik Optimizer automatically extracts the first argument from any function which ends
 * in `$`.
 *
 * This means that `foo$(arg0)` and `foo($(arg0))` are equivalent with respect to Qwik Optimizer.
 * The former is just a shorthand for the latter.
 *
 * For example, these function calls are equivalent:
 *
 * - `component$(() => {...})` is same as `component($(() => {...}))`
 *
 * ```tsx
 * export function myApi(callback: QRL<() => void>): void {
 *   // ...
 * }
 *
 * export const myApi$ = implicit$FirstArg(myApi);
 * // type of myApi$: (callback: () => void): void
 *
 * // can be used as:
 * myApi$(() => console.log('callback'));
 *
 * // will be transpiled to:
 * // FILE: <current file>
 * myApi(qrl('./chunk-abc.js', 'callback'));
 *
 * // FILE: chunk-abc.js
 * export const callback = () => console.log('callback');
 * ```
 *
 * @param fn - A function that should have its first argument automatically `$`.
 * @public
 */
// </docs>
export const implicit$FirstArg = <FIRST, REST extends any[], RET>(
  fn: (qrl: QRL<FIRST>, ...rest: REST) => RET
): ((qrl: FIRST, ...rest: REST) => RET) => {
  return function (first: FIRST, ...rest: REST): RET {
    return fn.call(null, dollar(first), ...rest);
  };
};
