import type { DecoratorContext, Model, ModelProperty, Type } from "@typespec/compiler";

export interface HttpPartOptions {
  readonly name?: string;
}

export interface ApplyMergePatchOptions {
  readonly visibilityMode: unknown;
}

export type PlainDataDecorator = (context: DecoratorContext, target: Model) => void;

export type HttpFileDecorator = (context: DecoratorContext, target: Model) => void;

export type HttpPartDecorator = (
  context: DecoratorContext,
  target: Model,
  type: Type,
  options: HttpPartOptions,
) => void;

/**
 * Performs the canonical merge-patch transformation on the given model and injects its
 * transformed properties into the target.
 */
export type ApplyMergePatchDecorator = (
  context: DecoratorContext,
  target: Model,
  source: Model,
  nameTemplate: string,
  options: ApplyMergePatchOptions,
) => void;

/**
 * Specify if inapplicable metadata should be included in the payload for the given entity.
 *
 * @param value If true, inapplicable metadata will be included in the payload.
 */
export type IncludeInapplicableMetadataInPayloadDecorator = (
  context: DecoratorContext,
  target: Type,
  value: boolean,
) => void;

/**
 * Marks a model that was generated by applying the MergePatch
 * transform and links to its source model
 */
export type MergePatchModelDecorator = (
  context: DecoratorContext,
  target: Model,
  source: Model,
) => void;

/**
 * Links a modelProperty mutated as part of a mergePatch transform to
 * its source property;
 */
export type MergePatchPropertyDecorator = (
  context: DecoratorContext,
  target: ModelProperty,
  source: ModelProperty,
) => void;

export type TypeSpecHttpPrivateDecorators = {
  plainData: PlainDataDecorator;
  httpFile: HttpFileDecorator;
  httpPart: HttpPartDecorator;
  applyMergePatch: ApplyMergePatchDecorator;
  includeInapplicableMetadataInPayload: IncludeInapplicableMetadataInPayloadDecorator;
  mergePatchModel: MergePatchModelDecorator;
  mergePatchProperty: MergePatchPropertyDecorator;
};
