import Binding, { IBindingPlugin } from '../binding';
export declare type IBindingStorage<T extends object> = {
    [key in keyof T]: T[key] extends object ? IBindingStorage<T[key]> : (ProxyHandler<T> | Binding<T[key]>);
};
export declare type IBoundPluginMap<T extends object> = {
    [key in keyof T]: T[key] extends object ? IBoundPluginMap<T[key]> : IBindingPlugin<T[key]>;
};
/**
  const BoundInstance = new Bound({
    prop: 'bar',
    nested: {
      prop: 'foo'
    }
  });

  BoundInstance.bindAndMap({
    test: 'prop',
    nestedProp: 'value'
  }, {
    prop: 'test',
    nested: {
      prop: 'nestedProp'
    }
  });
 */
export declare type BindObjectMap<T extends object> = {
    [key in keyof T]: T[key] extends object ? BindObjectMap<T[key]> : string;
};
export default abstract class BaseBound<T extends object> {
    plugins?: IBoundPluginMap<T> | undefined;
    /**
     * Stores bindings in a structure that is identical to the binding-prototype-object.
     */
    storage: IBindingStorage<T>;
    /**
     * A bound object created from a constuctor's snapshot object.
     *
     * Contains an instance of the Bound class itself by the `__bound__` key.
     */
    boundObject: T & {
        __bound__: BaseBound<T>;
    };
    /**
     * Creates an instance of BaseBound.
     * @param proto used as an object prototype for the creation of boundObject and storage. Doesn't become bound itself.
     * @param [plugins] to plug into the binding events.
     */
    constructor(proto: T, plugins?: IBoundPluginMap<T> | undefined);
    /**
     * Binds an object to all other current subscribers
     *
     * @template U used to capture the bound object type. Must extends original template type.
     * @param obj to bind
     * @param [twoWay] whether the binding should be two-way
     */
    abstract bind<U extends T>(obj: U, twoWay?: boolean): this;
    /**
     * [NOT_IMPLEMENTED] Maps the object of a different shape to the original binding object
     * @param obj target object to bind
     * @param mapToOriginal a map for target object's keys relative to the original binding object type
     * @param twoWay whether the binding should be two-way
     */
    bindAndMap<U>(obj: U, mapToOriginal: BindObjectMap<T>, twoWay?: boolean): this;
    /**
     * Unbinds an object and destroys all of its listeners
     *
     * @param obj reference of object to be unbound
     */
    abstract unbind<U extends T>(obj: U): U;
    /**
     * Global binding config. Changes affect all instances.
     */
    static readonly config: import("../config").IConfig;
    /**
     * Checks whether an object is already bound.
     *
     * @param obj an object ot check
     */
    static isBound(obj: any): boolean;
}
