import { Expression } from "../ast";
import { Database } from "./schema/Database";
import { Column } from "./schema/Column";
import { TableReference } from "./schema/TableReference";
import { DatabaseTrigger } from "./schema/DatabaseTrigger";
import { DatabaseFunction  } from "./schema/DatabaseFunction";
import { Index } from "./schema/Index";
import { TableID } from "./schema/TableID";
import { CacheUpdate } from "../Comparator/graph/CacheUpdate";

// TODO: apply I from SOLID
export interface IDatabaseDriver {
    query(sql: string): Promise<{rows: any[]}>;
    queryWithTimeout(sql: string, timeout: number): Promise<{rows: any[]}>;
    load(): Promise<Database>;
    unfreezeAll(dbState: Database): Promise<void>;
    createOrReplaceFunction(func: DatabaseFunction): Promise<void>;
    createOrReplaceLogFunction(func: DatabaseFunction): Promise<void>;
    dropFunction(func: DatabaseFunction): Promise<void>;
    createOrReplaceTrigger(trigger: DatabaseTrigger): Promise<void>;
    dropTrigger(trigger: DatabaseTrigger): Promise<void>;
    getType(expression: Expression): Promise<string>;
    commentColumn(column: Column): Promise<void>;
    createOrReplaceColumn(column: Column): Promise<void>;
    dropColumn(column: Column): Promise<void>;
    selectMinMax(table: TableID): Promise<MinMax>;
    selectNextIds(
        table: TableID,
        maxId: number,
        limit: number
    ): Promise<number[]>;
    /** update rows where id >= minId and id < maxId */
    updateCacheForRows(
        update: CacheUpdate,
        minId: number, maxId: number,
        timeout?: number
    ): Promise<void>;
    updateCacheLimitedPackage(
        update: CacheUpdate,
        limit: number,
        timeout?: number
    ): Promise<number[]>;
    terminateActiveCacheUpdates(): Promise<void>;
    dropIndex(index: Index): Promise<void>;
    createOrReplaceIndex(index: Index): Promise<void>;
    end(): void;
    disableTrigger(onTable: TableID, triggerName: string): Promise<void>;
    enableTrigger(onTable: TableID, triggerName: string): Promise<void>;
}

export interface MinMax {
    min: number | null;
    max: number | null;
}