import { Logger } from '@lordfokas/loggamus';
import { type Connection } from './DB.js';
import { SelectBuilder, type Filter } from './QueryBuilder.js';
import { Class, NS, UUID, SkipUUID, NamespacedUUID, EntityConfig, Primitive, TableFields } from './Structures.js';
import { Serializer } from './Serializer.js';
/** Define a new logger to send output to */
export declare function useLogger(logger: Logger): void;
type EClass<T> = typeof Entity & Class<T>;
export type FieldSet<T extends typeof Entity> = keyof (T["$config"]["fields"]) & keyof TableFields;
export declare class Entity {
    #private;
    static readonly Serializer: typeof Serializer;
    static readonly $config: EntityConfig;
    uuid?: UUID<NS>;
    /** Get one entity from this table, by UUID. */
    static uuid<K extends NS, T extends NamespacedUUID<K>, C extends EClass<T>, I extends InstanceType<C>>(this: C, db: Connection, uuid: UUID<K>, select?: FieldSet<C>): Promise<I[]>;
    /** Get all the entities from this table */
    static all<K extends NS, T extends NamespacedUUID<K>, C extends EClass<T>, I extends InstanceType<C>>(this: C, db: Connection, select?: FieldSet<C>): Promise<I[]>;
    /** Get all entities from this table where {field} is in {list}. */
    static in<K extends NS, T extends NamespacedUUID<K>, C extends EClass<T>, I extends InstanceType<C>>(this: C, db: Connection, field: string, list: Primitive[], select?: FieldSet<C>): Promise<I[]>;
    /** Insert all Entities in the given list as a single query. All Entities must be of this type. */
    static bulkInsert<C extends EClass<any>>(this: C, db: Connection, entities: InstanceType<C>[]): Promise<any>;
    /** Create one or more Entities in the database. If many, a bulk query is written. */
    static create<C extends EClass<any>>(this: C, db: Connection, ...entities: InstanceType<C>[]): Promise<any>;
    /** Actually create the entities respecting the inheritance chain. */
    private static create_chain;
    /** Update one or more database rows with the data contained in this Entity */
    static update<C extends EClass<any>>(this: C, db: Connection, entity: InstanceType<C>, update?: FieldSet<C>, filters?: Filter[]): Promise<any>;
    private static do_update;
    /** Read one or more records from the database. If Connection === false returns the query builder instead */
    static read<C extends EClass<any>>(this: C, db: false, select?: FieldSet<C>, filters?: Filter[]): Promise<SelectBuilder>;
    static read<C extends EClass<any>>(this: C, db: Connection, select?: FieldSet<C>, filters?: Filter[]): Promise<InstanceType<C>[]>;
    /** Create queries for table inheritance. */
    private static read_parent;
    protected static $of<C extends EClass<any>>(this: C, row: object, fn?: (dlo: InstanceType<C>, row: object) => void): InstanceType<C>;
    static isSubtype(): boolean;
    static getSupertype(): EClass<any>;
    static getFields<C extends EClass<any>>(this: C, entity: InstanceType<C>, fields?: FieldSet<C>, allowNull?: boolean): string[];
    /** Hook to fire before creation to make adjustements to entities. */
    protected static beforeCreate<C extends EClass<any>>(this: C, ...entity: InstanceType<C>[]): void;
    /** Build an Entity from a given object */
    constructor(obj?: object);
    /**
     * Build an Entity from a database row.
     * Scans this row for fields that belong to the same table as this object.
     * Any matching fields are injected into the object.
     * This is done by expecting fields to be prefixed with the table's 2-letter code.
     */
    protected $ingest(row: object, prefix?: string): this;
    /** Generate a UUID for this Entity. Will fail if the field is already filled. */
    protected generateUUID(): void;
    /** Generate a zero UUID for this Entity. Will fail if the field is already filled. */
    protected generateZERO(): void;
    /** Get the list of fields in this Entity, with UUIDs in front and sorted */
    private prioritizeUUIDs;
    /**
     * Insert this Entity into the database.
     * If skip isn't present, a UUID will be generated automatically.
     */
    insert(db: Connection, skip?: SkipUUID): Promise<any>;
    /**
     * Update this Entity's DB record. Optionally specify a stricter list of fields to update.
     * Will fail if a UUID isn't present.
     */
    update<C extends typeof Entity>(this: InstanceType<C>, db: Connection, fields?: FieldSet<C>): Promise<any>;
    /** Upserts (update or insert) this Entity, depending on wether or not this object has a UUID. */
    upsert<C extends typeof Entity>(this: InstanceType<C>, db: Connection, fields?: FieldSet<C>): Promise<any>;
    /**
     * Creates a list of fields for a SELECT query, aliased as XX_col_name
     * where XX is this table's 2-letter code.
     */
    static ALIAS(columns: string[], p_tbl?: string, p_col?: string): string;
    /** Creates a list of fields for a SELECT query */
    static COL(columns: string[], prefix?: string): string;
    /** Returns this table aliased with its 2-letter code for use in queries. */
    static TABLE(prefix?: string): string;
    /** Generate a zero-filled UUID with an appropriate size for this table's PK. */
    protected static ZERO(): UUID<NS>;
    /**
     * Generate a UUID with an appropriate size for this table's PK.
     * A different generator can be provided, default is UUID v4.
     */
    protected static UUID(gen?: () => string): UUID<NS>;
    /** Transforms a JSON structure into concrete entities */
    static fromJSON<T extends Entity>(this: EClass<T>, data: string): T;
    /** Transforms an object into concrete entities */
    static fromObject<T extends Entity>(this: EClass<T>, data: object): T;
    /** Validate that a type has a correct structure */
    protected static $validateOwnType<T extends Entity>(this: EClass<T>, obj: T): void;
    /** Shortcut to get the class config from an instance */
    private get $config();
}
export {};
