import * as IO from "../../helpers/io.js";
import { EntityLink } from "../links/entityLink.js";
import { AnyRecordLink, RecordLink } from "../links/recordLink.js";
import type { SubscriptionRecord } from "../recordTypes/subscriptionRecord.js";
import { RecordKey } from "./recordKey.js";
import { RecordPermissions } from "./recordPermissions.js";
import { AnyRecordType, RAnyRecordType } from "./recordType.js";
export type RecordId<T extends AnyRecord | NoContentRecord> = string & {
    _type?: T;
};
export type VersionHash<T extends AnyRecord | NoContentRecord> = string & {
    _type?: T;
};
export declare enum RecordSource {
    SELF = "self",
    RESOLUTION = "resolution",
    NOTIFICATION = "notification",
    NOTIFICATION_UNKNOWN = "notification_unknown",
    SUBSCRIPTION = "subscription",
    PROXY = "proxy"
}
export declare enum RecordMode {
    SYNCED = "synced",
    LOCAL = "local"
}
export declare enum NoContentRecordAction {
    DELETE = "delete",
    LOCAL = "local",
    REPORT = "report",
    LEAVE = "leave"
}
export interface RecordVersion<T extends AnyRecord | NoContentRecord> {
    author: EntityLink;
    hash: VersionHash<T> | undefined;
    createdAt: Date;
    receivedAt: Date | undefined;
    parentHash?: string;
}
export interface Record<T extends AnyRecordType, C> {
    author: EntityLink;
    id: RecordId<Record<T, C>>;
    source: `${RecordSource}`;
    createdAt: Date;
    receivedAt: Date | undefined;
    version: RecordVersion<Record<T, C>> | undefined;
    permissions: RecordPermissions;
    type: T;
    content: C;
    mode: `${RecordMode}`;
}
export type AnyRecord = Record<AnyRecordType, any>;
export type UnknownRecord = Record<never, never>;
export interface NoContentRecord {
    author: EntityLink;
    id: RecordId<NoContentRecord>;
    source: `${RecordSource}`;
    createdAt: Date;
    receivedAt: Date | undefined;
    version: RecordVersion<NoContentRecord> | undefined;
    permissions: RecordPermissions;
    type: AnyRecordType;
    noContent: {
        action: `${NoContentRecordAction}`;
        links?: unknown;
    };
    mode: `${RecordMode}`;
}
export interface CleanRecordType<T extends AnyRecord> extends IO.Type<T, any, unknown> {
    RType: IO.Type<T["type"], any, unknown>;
    RContent: IO.Type<T["content"], any, unknown>;
    type: T["type"];
    link: RecordLink<T>;
    new: (entity: string, content: T["content"], options?: NewRecordOptions) => T;
    update: (entity: string, record: T, content: T["content"], options?: NewRecordOptions) => T;
    subscribe: (entity: string, publisherEntity: string, options?: NewSubscriptionOptions) => SubscriptionRecord;
}
interface SubscriptionRecordContainer {
    SubscriptionRecord: typeof SubscriptionRecord;
}
export declare const subscriptionRecordContainer: SubscriptionRecordContainer;
declare class RecordClassBase<T extends RAnyRecordType, C extends IO.Any> extends IO.Type<Record<IO.TypeOf<T>, IO.TypeOf<C>>, unknown, unknown> {
    RType: T;
    RContent: C;
    constructor(RType: T, RContent: C);
}
declare class RecordClass<T extends RAnyRecordType, C extends IO.Any> extends RecordClassBase<T, C> {
    type: IO.TypeOf<T>;
    constructor(type: IO.TypeOf<T>, RType: T, RContent: C);
    link: RecordLink<IO.TypeOf<this>>;
    new(entity: string, content: IO.TypeOf<C>, options?: NewRecordOptions): IO.TypeOf<this>;
    update(entity: string, record: Record<IO.TypeOf<T>, IO.TypeOf<C>>, content: IO.TypeOf<C>, options?: NewRecordOptions): IO.TypeOf<this>;
    subscribe(entity: string, publisherEntity: string, options?: NewSubscriptionOptions): SubscriptionRecord;
}
declare function record<T extends RAnyRecordType, C extends IO.Any>(type: IO.TypeOf<T>, RType: T, RContent: C): RecordClass<T, C>;
declare function cleanRecord<T extends AnyRecord>(RRecord: CleanRecordType<T>): CleanRecordType<T>;
export declare const AnyRecord: RecordClassBase<IO.AnyC, IO.AnyC>;
export type RAnyRecord = IO.Type<AnyRecord, unknown, unknown>;
export declare const RNoContentRecord: IO.Type<NoContentRecord>;
export type RAnyEventRecord = RAnyRecord | IO.Type<NoContentRecord, unknown, unknown> | IO.Type<AnyRecord | NoContentRecord, unknown, unknown>;
export interface NewRecordOptions {
    id?: string;
    permissions?: RecordPermissions;
    mode?: `${RecordMode}`;
}
export interface UpdateRecordOptions {
    permissions?: RecordPermissions;
}
declare function buildNoContentRecord(entity: string, record: AnyRecord, action?: `${NoContentRecordAction}`): NoContentRecord;
export interface NewSubscriptionOptions {
    id?: RecordId<SubscriptionRecord>;
    readPermissions?: RecordPermissions["read"];
}
declare function isSameRecord(record1: AnyRecord, record2: AnyRecord): boolean;
declare function isPublicRecord(record: AnyRecord): boolean;
declare function recordHasType<T extends AnyRecord>(record: AnyRecord, type: CleanRecordType<T>): record is T;
declare function updateToSynced<T extends AnyRecord>(record: T): T;
declare function updateToSelf<T extends AnyRecord>(record: T): T;
declare function updateToResolution<T extends AnyRecord>(record: T): T;
declare function recordToKey<T extends AnyRecord | NoContentRecord>(record: T): RecordKey<T>;
declare function recordToLink<T extends AnyRecord>(record: T): RecordLink<T>;
declare function recordToVersionHash<T extends AnyRecord | NoContentRecord>(record: T): VersionHash<T>;
declare function noContentRecordToLink(record: NoContentRecord): AnyRecordLink;
export declare const Record: {
    io: typeof record;
    ioClean: typeof cleanRecord;
    isSame: typeof isSameRecord;
    isPublic: typeof isPublicRecord;
    hasType: typeof recordHasType;
    toSynced: typeof updateToSynced;
    toSelf: typeof updateToSelf;
    toResolution: typeof updateToResolution;
    toKey: typeof recordToKey;
    toLink: typeof recordToLink;
    toVersionHash: typeof recordToVersionHash;
    noContentToLink: typeof noContentRecordToLink;
    delete: typeof buildNoContentRecord;
};
export {};
