import {Awaitable, Constructable, Maybe, OrderDirection, QueryRow} from '@extollo/lib'

export enum FieldType {
    text = 'text',
    textarea = 'textarea',
    html = 'html',
    email = 'email',
    number = 'number',
    integer = 'integer',
    date = 'date',
    select = 'select',
    bool = 'bool',
}

enum ResourceAction {
    create = 'create',
    read = 'read',
    readOne = 'readOne',
    update = 'update',
    delete = 'delete',
}

export enum Renderer {
    text = 'text',
    html = 'html',
    bool = 'bool',
    date = 'date',
    time = 'time',
    datetime = 'datetime',
}

const allResourceActions = [
    ResourceAction.create, ResourceAction.read, ResourceAction.readOne,
    ResourceAction.update, ResourceAction.delete,
]

export type CobaltAction = {
    slug: string,
    title: string,
    color: string,
    icon: string,
    type: 'route',
    route: string,
    overall?: boolean,
}

export type FieldBase = {
    key: string,
    display: string,
    type: FieldType,
    required: boolean,
    sort?: 'asc' | 'desc',
    renderer?: Renderer,
    readonly?: boolean,
    helpText?: string,
    placeholder?: string,
    queryable?: boolean,
    hideOn?: {
        form?: boolean,
        listing?: boolean,
    },
}

export type SelectOptions = {display: string, value: any}[]

export type RemoteSelectDefinition = {
    displayFrom: string,
    valueFrom: string,
    source: DataSource,
}

export type FieldDefinition = FieldBase
    | FieldBase & { type: FieldType.select, multiple?: boolean, options: SelectOptions }
    | FieldBase & { type: FieldType.select } & RemoteSelectDefinition

export interface DataSourceController {
    read(): Awaitable<QueryRow[]>
    readOne(id: any): Awaitable<Maybe<QueryRow>>
    insert(row: QueryRow): Awaitable<QueryRow>
    update(id: any, row: QueryRow): Awaitable<QueryRow>
    delete(id: any): Awaitable<void>
}

export type DataSource =
    { collection: string }
    | { controller: Constructable<DataSourceController> }
    | { method: Constructable<() => Awaitable<QueryRow[]>> }

export interface ResourceConfiguration {
    key: string,
    source: DataSource,
    primaryKey: string,
    orderField?: string,
    orderDirection?: OrderDirection,
    generateKeyOnInsert?: () => string|number,
    processBeforeInsert?: (row: QueryRow) => Awaitable<QueryRow>,
    processAfterRead?: (row: QueryRow) => Awaitable<QueryRow>,
    display: {
        field?: string,
        singular: string,
        plural: string,
    },
    supportedActions: ResourceAction[],
    otherActions: CobaltAction[],
    fields: FieldDefinition[],
}

export { ResourceAction, allResourceActions }
