import type { Refkey } from "@alloy-js/core";
import { For, List, refkey } from "@alloy-js/core";
import * as ts from "@alloy-js/typescript";
import { useTsp } from "@typespec/emitter-framework";
import { ClassMethod } from "@typespec/emitter-framework/typescript";
import type * as cl from "@typespec/http-client";
import { useClientLibrary } from "@typespec/http-client";
import { flattenClients } from "../utils/client-discovery.js";
import { buildClientParameters } from "../utils/parameters.jsx";
import { getClientcontextDeclarationRef } from "./client-context/client-context-declaration.jsx";
import { getClientContextFactoryRef } from "./client-context/client-context-factory.jsx";
import { getOperationParameters } from "./operation-parameters.jsx";
export interface ClientProps {}
export function Client(props: ClientProps) {
const { $ } = useTsp();
const namePolicy = ts.useTSNamePolicy();
const { topLevel } = useClientLibrary();
return (
{(client) => {
const fileName = namePolicy.getName($.client.getName(client), "variable");
const flatClients = flattenClients(client);
return (
{(client) => }
);
}}
);
}
export interface ClientClassProps {
client: cl.Client;
}
export function getClientClassRef(client: cl.Client) {
return refkey(client.type, "client-class");
}
function getClientContextFieldRef(client: cl.Client) {
return refkey(client.type, "client-context");
}
export function ClientClass(props: ClientClassProps) {
const { $ } = useTsp();
const namePolicy = ts.useTSNamePolicy();
const clientName = namePolicy.getName($.client.getName(props.client), "class");
const contextMemberRef = getClientContextFieldRef(props.client);
const contextDeclarationRef = getClientcontextDeclarationRef(props.client);
const clientClassRef = getClientClassRef(props.client);
const subClients = props.client.subClients;
const operations = props.client.operations;
return (
{(subClient) => }
{(op) => {
const parameters = getOperationParameters(op.httpOperation, refkey());
const args = parameters.flatMap((p) => p.refkey);
const isPaging = Boolean($.operation.getPagingMetadata(op.httpOperation.operation));
return (
return{" "}
;
);
}}
);
}
interface SubClientClassFieldProps {
client: cl.Client;
}
function getSubClientClassFieldRef(client: cl.Client) {
return refkey(client.type, "client-field");
}
function SubClientClassField(props: SubClientClassFieldProps) {
const { $ } = useTsp();
const parent = props.client.parent;
// If sub client has different parameters than client, don't add it as a subclass field
// Todo: We need to detect the extra parameters and make this field a factory for the subclient
if (parent && !$.client.haveSameConstructor(props.client, parent)) {
return null;
}
const namePolicy = ts.useTSNamePolicy();
const fieldName = namePolicy.getName($.client.getName(props.client), "class");
const subClientClassRef = getClientClassRef(props.client);
const subClientFieldRef = getSubClientClassFieldRef(props.client);
return ;
}
interface ClientConstructorProps {
client: cl.Client;
}
function ClientConstructor(props: ClientConstructorProps) {
const { $ } = useTsp();
const subClients = props.client.subClients.filter((sc) =>
$.client.haveSameConstructor(sc, props.client),
);
const clientContextFieldRef = getClientContextFieldRef(props.client);
const clientContextFactoryRef = getClientContextFactoryRef(props.client);
const constructorParameters = buildClientParameters(props.client, refkey());
const args = Object.values(constructorParameters).map((p) => p.refkey);
return (
{clientContextFieldRef} ={" "}
;
{(subClient) => {
const subClientFieldRef = getSubClientClassFieldRef(subClient);
const subClientArgs = calculateSubClientArgs(subClient, constructorParameters);
return (
<>
{subClientFieldRef} = ;
>
);
}}
);
}
function calculateSubClientArgs(subClient: cl.Client, parentParams: ts.ParameterDescriptor[]) {
const subClientParams = buildClientParameters(subClient, refkey()).map((p) => p.name);
return parentParams
.filter(({ name }) => subClientParams.includes(name))
.flatMap((p) => (p.refkey ? p.refkey : []));
}
export interface NewClientExpressionProps {
client: cl.Client;
args: Refkey[];
}
function NewClientExpression(props: NewClientExpressionProps) {
const clientConstructorRef = getClientClassRef(props.client);
return (
<>
new
>
);
}