/**
 * Copyright (c) 2018-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
 *
 * @author David Sehnal <david.sehnal@gmail.com>
 */
import { Task } from '../mol-task/index.js';
import { StateObject, StateObjectCell } from './object.js';
import { StateTransform } from './transform.js';
import { ParamDefinition as PD } from '../mol-util/param-definition.js';
import { StateAction } from './action.js';
import { StateTreeSpine } from './tree/spine.js';
export { Transformer as StateTransformer };
interface Transformer<A extends StateObject = StateObject, B extends StateObject = StateObject, P extends {} = any> {
    apply(parent: StateTransform.Ref, params?: P, props?: Partial<StateTransform.Options>): StateTransform<this>;
    toAction(): StateAction<A, void, P>;
    readonly namespace: string;
    readonly id: Transformer.Id;
    readonly definition: Transformer.Definition<A, B, P>;
    /** create a fresh copy of the params which can be edited in place */
    createDefaultParams(a: A, globalCtx: unknown): P;
}
declare namespace Transformer {
    type Id = string & {
        '@type': 'transformer-id';
    };
    type Params<T extends Transformer<any, any, any>> = T extends Transformer<any, any, infer P> ? P : unknown;
    type From<T extends Transformer<any, any, any>> = T extends Transformer<infer A, any, any> ? A : unknown;
    type To<T extends Transformer<any, any, any>> = T extends Transformer<any, infer B, any> ? B : unknown;
    type Cell<T extends Transformer<any, any, any>> = T extends Transformer<any, infer B, any> ? StateObjectCell<B> : unknown;
    function getParamDefinition<T extends Transformer>(t: T, a: From<T> | undefined, globalCtx: unknown): PD.For<Params<T>>;
    function is(obj: any): obj is Transformer;
    interface ApplyParams<A extends StateObject = StateObject, P extends {} = {}> {
        a: A;
        params: P;
        /** A cache object that is purged each time the corresponding StateObject is removed or recreated. */
        cache: unknown;
        spine: StateTreeSpine;
        dependencies?: {
            [k: string]: StateObject<unknown>;
        };
    }
    interface UpdateParams<A extends StateObject = StateObject, B extends StateObject = StateObject, P extends {} = {}> {
        a: A;
        b: B;
        oldParams: P;
        newParams: P;
        /** A cache object that is purged each time the corresponding StateObject is removed or recreated. */
        cache: unknown;
        spine: StateTreeSpine;
        dependencies?: {
            [k: string]: StateObject<unknown>;
        };
    }
    interface AutoUpdateParams<A extends StateObject = StateObject, B extends StateObject = StateObject, P extends {} = {}> {
        a: A;
        b: B;
        oldParams: P;
        newParams: P;
    }
    interface DisposeParams<B extends StateObject = StateObject, P extends {} = {}> {
        b: B | undefined;
        params: P | undefined;
        cache: unknown;
    }
    enum UpdateResult {
        Unchanged = 0,
        Updated = 1,
        Recreate = 2,
        Null = 3
    }
    /** Specify default control descriptors for the parameters */
    interface DefinitionBase<A extends StateObject = StateObject, B extends StateObject = StateObject, P extends {} = {}> {
        /**
         * Apply the actual transformation. It must be pure (i.e. with no side effects).
         * Returns a task that produces the result of the result directly.
         */
        apply(params: ApplyParams<A, P>, globalCtx: unknown): Task<B> | B;
        /**
         * Attempts to update the entity in a non-destructive way.
         * For example changing a color scheme of a visual does not require computing new geometry.
         * Return/resolve to undefined if the update is not possible.
         */
        update?(params: UpdateParams<A, B, P>, globalCtx: unknown): Task<UpdateResult> | UpdateResult;
        /** Determine if the transformer can be applied automatically on UI change. Default is false. */
        canAutoUpdate?(params: AutoUpdateParams<A, B, P>, globalCtx: unknown): boolean;
        /** Test if the transform can be applied to a given node */
        isApplicable?(a: A, globalCtx: unknown): boolean;
        /** By default, returns true */
        isSerializable?(params: P): {
            isSerializable: true;
        } | {
            isSerializable: false;
            reason: string;
        };
        /** Parameter interpolation */
        interpolate?(src: P, target: P, t: number, globalCtx: unknown): P;
        /**
         * Cleanup resources
         *
         * Automatically called on deleting an object and on recreating it
         * (i.e. when update returns UpdateResult.Recreate or UpdateResult.Null)
         *
         * Not called on UpdateResult.Updated because the resources might not
         * have been invalidated. In this case, the possible cleanup has to be handled
         * manually.
         */
        dispose?(params: DisposeParams<B, P>, globalCtx: unknown): void;
        /** Custom conversion to and from JSON */
        readonly customSerialization?: {
            toJSON(params: P, obj?: B): any;
            fromJSON(data: any): P;
        };
    }
    interface Definition<A extends StateObject = StateObject, B extends StateObject = StateObject, P extends {} = {}> extends DefinitionBase<A, B, P> {
        readonly name: string;
        readonly from: StateObject.Ctor[];
        readonly to: StateObject.Ctor[];
        readonly display: {
            readonly name: string;
            readonly description?: string;
        };
        params?(a: A | undefined, globalCtx: unknown): {
            [K in keyof P]: PD.Any;
        };
        /**
         * Decorators are special Transformers mapping the object to the same type.
         *
         * Special rules apply:
         * - applying decorator always "inserts" it instead
         * - applying to a decorated Transform is applied to the decorator instead (transitive)
         */
        readonly isDecorator?: boolean;
    }
    function getAll(): Transformer<any, any, any>[];
    function get(id: string): Transformer;
    function fromType(type: StateObject.Type): ReadonlyArray<Transformer>;
    function create<A extends StateObject, B extends StateObject, P extends {} = {}>(namespace: string, definition: Definition<A, B, P>): Transformer<any, any, any>;
    function factory(namespace: string): <A extends StateObject, B extends StateObject, P extends {} = {}>(definition: Definition<A, B, P>) => Transformer<any, any, any>;
    function builderFactory(namespace: string): Builder.Root;
    namespace Builder {
        interface Type<A extends StateObject.Ctor, B extends StateObject.Ctor, P extends {}> {
            name: string;
            from: A | A[];
            to: B | B[];
            /** The source StateObject can be undefined: used for generating docs. */
            params?: PD.For<P> | ((a: StateObject.From<A> | undefined, globalCtx: any) => PD.For<P>);
            display?: string | {
                name: string;
                description?: string;
            };
            isDecorator?: boolean;
        }
        interface Root {
            <A extends StateObject.Ctor, B extends StateObject.Ctor, P extends {}>(info: Type<A, B, P>): Define<StateObject.From<A>, StateObject.From<B>, PD.Normalize<P>>;
        }
        interface Define<A extends StateObject, B extends StateObject, P extends {}> {
            (def: DefinitionBase<A, B, P>): Transformer<A, B, P>;
        }
        function build(namespace: string): Root;
    }
    function build(namespace: string): Builder.Root;
    const ROOT: Transformer<any, any, any>;
}
