import type { AutosizeTypes } from "../frontend/components/edit/scripts/autosize"
import type { Input } from "./Input"
import type { Animation } from "./Output"
import type { Cropping, Resolution } from "./Settings"

export interface Shows {
    [key: string]: Show
}

export interface Show {
    name: string
    id?: string // this id should not be stored (but often used in the program as a temporary value)
    origin?: string // "pco" | "churchApps" | "hymnary", etc.
    private?: boolean // hide from drawer
    locked?: boolean // disable edits
    category: null | ID
    quickAccess?: any
    reference?: {
        type: "calendar" | "scripture" | "lessons" | "canva" | "interaction"
        data: any
    }
    settings: {
        activeLayout: ID
        // resolution?: Resolution
        template: null | ID
        customAction?: string // special custom trigger
        customFonts?: { name: string; path: string }[]
    }
    timestamps: {
        created: number
        modified: null | number
        used: null | number
    }
    metadata?: {
        // override: boolean
        // display: string
        // template: string
        tags?: string[]
    }
    meta: {
        number?: string
        title?: string
        artist?: string
        author?: string
        composer?: string
        publisher?: string
        copyright?: string
        CCLI?: string
        year?: string
        key?: string
    }
    slides: { [key: ID]: Slide }
    layouts: { [key: ID]: Layout }
    media: { [key: ID]: Media }
    midi?: { [key: ID]: Action }
}

export interface TrimmedShows {
    [key: string]: TrimmedShow
}
export interface TrimmedShow {
    name: string
    origin?: string
    category: null | ID
    timestamps: {
        created: number
        modified: null | number
        used: null | number
    }
    quickAccess?: any
    private?: boolean
    locked?: boolean
}

export interface ShowList extends TrimmedShow {
    id: string
    match?: number
    originalMatch?: number
}

export interface Slide {
    id?: string // used for reference, but might not be removed
    group: null | string
    color: null | string
    globalGroup?: string
    locked?: boolean // lock slide group to prevent changes
    settings: {
        template?: string
        background?: boolean
        color?: string
        backgroundImage?: string
        resolution?: Resolution
    }
    children?: string[]
    notes: string
    items: Item[]
    timeline?: Timeline

    customDynamicValues?: { [key: string]: string | [string, string][] } // used for scripture slides
}

export interface Item {
    id?: string
    lines?: Line[]
    list?: List
    auto?: boolean // DEPRECATED - use textFit
    textFit?: AutosizeTypes // auto size text fix option (default: shrinkToFit)
    autoFontSize?: number // only used to store the calculated auto size text size
    previewAutoFontSize?: number // only used to store the calculated auto size text size for the preview
    style: string
    align?: string
    specialStyle?: any // line gap && line background
    media?: any
    cropping?: Cropping // in percentage based on original image size
    // timer?: Timer // pre 0.8.3 // also local backup?
    timer?: { id: string; [key: string]: any }
    timerId?: string // pre 1.5.0
    clock?: Clock
    events?: DynamicEvent
    type?: ItemType
    decoration?: boolean // ppt imported shapes & scripture items (no selection directly)

    src?: string // media item path
    customSvg?: string
    device?: any // camera
    fit?: string
    filter?: string
    flipped?: boolean
    flippedY?: boolean // media item
    blend?: string
    muted?: boolean // media item
    loop?: boolean // media item
    speed?: number // media item
    variable?: any
    web?: any
    tracker?: any // slide progress tracker item data
    bindings?: string[] // bind item to stage or an output
    actions?: any // showTime | hideTime | transition
    clickReveal?: boolean
    lineReveal?: boolean
    chords?: { enabled?: boolean; color?: string; size?: number; offsetY?: number }
    scrolling?: Scrolling
    button?: { press?: string; release?: string } // click actions
    weather?: Weather
    visualizer?: any
    captions?: any
    language?: string // used to store auto localized text
    fromTemplate?: boolean // these will be removed if another template is applied
    // media: fit, startAt, endAt
    // tag?: string; // p, div????
    conditions?: { [key: string]: Condition }
    chart?: {
        type?: string
        data?: string
        holeSize?: number
    }
    table?: {
        headers?: boolean
        borderColor?: string
        borderWidth?: number
        rows: {
            cells: {
                text: string
                style?: string
            }[]
        }[]
    }
}

export interface LayoutRef {
    type: "parent" | "child"
    layoutId: string
    index: number
    layoutIndex: number
    id: string
    children?: string[]
    parent?: { id: string; index: number; layoutIndex: number }
    data: SlideData

    // slides.ts mover
    clone?: boolean
    newType?: "parent" | "child"
    replacesParent?: boolean
}

export interface ShowGroups {
    [key: string]: ShowGroup
}
export interface ShowGroup {
    name: string
    color: string
    default?: boolean

    template?: string
    shortcut?: string
}

export interface Timer {
    id?: string
    name: string
    type: "counter" | "clock" | "event" | "pco_live"
    viewType?: "time" | "line" | "circle"
    circleMask?: boolean
    showHours?: boolean // use just minutes or minutes and hours
    start?: number
    end?: number
    startDynamic?: string
    endDynamic?: string
    event?: string
    time?: string

    // PCO Live
    pco?: {
        serviceTypeId: string
        planId: string
        countdownType: "end_on_time" | "full_length" | "end_service"
    }

    warn?: boolean
    warnOffset?: number
    warnColor?: string
    warnFlash?: boolean

    overflow?: boolean
    overflowColor?: string
    overflowFlash?: boolean

    tags?: string[]

    // format?: string
    // paused?: boolean
}

export interface Clock {
    type: "digital" | "analog" | "custom"
    dateFormat: string
    showTime?: boolean
    seconds?: boolean

    // custom:
    customFormat?: string
    offsetDays?: number
}

export interface DynamicEvent {
    maxEvents: number
    startDaysFromToday: number
    justOneDay: boolean
    enableStartDate: boolean
    startDate?: string
    startTime?: string
    fromTime?: string
    toTime?: string
}

export interface Scrolling {
    type: "none" | "top_bottom" | "bottom_top" | "left_right" | "right_left"
    speed?: number
    gap?: number
}

// pre 1.5.0
// export interface Condition {
//     scenario: string
//     values: { [key: string]: string }[]
// }
// [outer_or, [outer_and, [inner_or, [inner_and, [content, {}}]]]]]
export type Condition = ConditionValue[][][][]
export interface ConditionValue {
    [key: string]: string
}

export interface Weather {
    size?: number
    latitude?: number
    longitude?: number
    altitude?: number
    useFahrenheit?: boolean
    longRange?: boolean
}

export interface Line {
    align: string
    text: {
        value: string
        style: string
        customType?: string // "disableTemplate"
        sourceDynamicKey?: string // used for scripture slides to link back to the dynamic value key (only scripture_text currently)
    }[]
    chords?: Chords[]
}

export interface List {
    enabled?: boolean
    style?: string
    interval?: number
    items?: ListItem[]
}
export interface ListItem {
    text: string
    icon?: string
}

export interface Chords {
    id: string
    pos: number
    key: string
}

export interface Layout {
    id?: string
    name: string
    notes: string
    timeline?: Timeline
    recording?: Recording[] // deprecated
    slides: SlideData[]
}

export interface Timeline {
    // id: string
    // name: string
    actions: TimelineAction[]
    loop?: boolean
}

export interface TimelineAction {
    id: string
    time: number // ms
    duration?: number // ms (media)
    name: string
    color?: string
    type: string // "action" | "slide" | "show" | "audio" | "style"
    easing?: { type?: "cubic-bezier"; x1: number; y1: number; x2: number; y2: number }

    data: {
        id?: string // slide/action/show
        path?: string // audio
        index?: number // slide
        layoutId?: string // show
        triggers?: string[] // action
        actionValues?: any // action
        // "style":
        // text currently changes all the "text" styles in the item
        indexes?: number[] // item indexes
        type?: string // "item" | "text"
        key?: string // style key
        value?: string | number // style key value
    }
}

// deprecated
export interface Recording {
    id: string
    layoutAtRecording: string // store layout ids to detect changes
    sequence: {
        time: number
        slideRef: { id: string; index: number }
    }[]
}

export interface SlideData {
    id: ID
    disabled?: boolean
    parent?: ID // layout ref
    children?: { [key: string]: any } // layout slide
    color?: null | string
    nextTimer?: number // next slide timer
    transition?: Transition
    // filterEnabled?: ["background", "foreground"] // pre 1.4.4
    filter?: string
    end?: boolean // go to start
    timer?: number
    background?: string // set backgorund action?
    overlays?: string[]
    effects?: string[]
    audio?: string[]

    mics?: { id: string; name: string }[]
    mediaTransition?: Transition
    remove?: boolean // slides.ts remove parent

    actions?: {
        slideActions?: SlideAction[]

        receiveMidi?: string
        nextAfterMedia?: boolean
        animate?: Animation // DEPRECATED!!
        slide_shortcut?: { key: string }
        startShow?: { id: string }

        clearBackground?: boolean
        clearOverlays?: boolean
        clearAudio?: boolean
        stopTimers?: boolean
        trigger?: string
        audioStream?: string
        outputStyle?: string // deprecated
        startTimer?: boolean
    }
    // actions?: {} // to begininng / index, clear (all), start timer, start audio/music ++
    bindings?: string[] // bind slide to an output
    breakDuration?: number // seconds spent on "break" slide (used for countdown display)
}

export interface SlideAction {
    id: string
    name?: string
    triggers: string[]
    actionValues?: { [key: string]: any }
    customData?: { [key: string]: { [key: string]: any } } // currently only used for overrideCategoryAction
}

export interface Transition {
    type: TransitionType
    duration: number
    easing: string
    fadeInOffset?: number // when to start fading in (default = 50%)
    delay?: number // item in/out wait
    custom?: any // e.g. transition direction

    between?: TransitionData
    in?: TransitionData
    out?: TransitionData
}

export interface TransitionData {
    type: TransitionType
    duration: number
    easing: string
    delay?: number // item in/out wait
}

export interface AnimationData {
    id?: string
    animation?: Animation
    transitions?: { [key: string]: string[] }
    styles?: { [key: string]: string[] }
    style?: { [key: string]: string }
    newIndex?: number
}

export interface Media {
    // name?: string
    id?: string
    name?: string
    path?: string
    cameraGroup?: string
    type?: MediaType
    muted?: boolean
    loop?: boolean
    filters?: string
    base64?: string // saving media data
    cloud?: { [key: string]: string }
}

export interface Action {
    name: string
    customIcon?: string // file path
    triggers: string[]
    actionValues?: any
    tags?: string[]
    // action?: string
    // actionData?: any
    // play specific show slide directly from midi input
    shows?: {
        id: string
        // layoutId: string
        // index: number
    }[]
    customActivation?: string
    keypressActivate?: string
    enabled?: boolean // should customActivation trigger
    midiEnabled?: boolean
    midi?: MidiValues

    // deprecated values
    startupEnabled?: boolean
    specificActivation?: string
}

export interface MidiValues {
    input?: string
    output?: string
    type: "noteon" | "noteoff" | "control"
    values: {
        channel: number
        // Note
        note?: number
        velocity?: number
        // CC
        controller?: number
        value?: number
    }
}

export type EmitterTypes = "osc" | "http" | "midi"
export interface EmitterTemplateValue {
    name: string
    value: string | { note?: number; velocity?: number; channel?: number }
}
export interface EmitterTemplate {
    name: string
    description?: string
    inputs: EmitterTemplateValue[]
}
export interface EmitterInputs {
    signal?: Input[]
}
export interface Emitter {
    name: string
    description?: string
    type: EmitterTypes
    signal?: any
    templates?: { [key: string]: EmitterTemplate }
    data?: string // custom (OSC) data
}

//

export interface Overlays {
    [key: ID]: Overlay
}
export interface Overlay {
    isDefault?: boolean
    name: string
    color: null | string
    category: null | string
    modified?: number // cloud sync
    items: Item[]
    locked?: boolean
    actions?: any[]
    placeUnderSlide?: boolean
    displayDuration?: number
}

export interface Templates {
    [key: ID]: Template
}
export interface Template {
    isDefault?: boolean
    name: string
    color: null | string
    category: null | string
    modified?: number // cloud sync
    settings?: TemplateSettings
    items: Item[]
}
export interface TemplateStyleOverride {
    id: string
    pattern: string
    globalRegex?: string
    templateId?: string
}
export interface TemplateSettings {
    mode?: "default" | "scripture" | "item" | "text"
    resolution?: Resolution
    backgroundColor?: string
    backgroundPath?: string
    overlayId?: string
    firstSlideTemplate?: string
    maxLinesPerSlide?: number | string // auto break slides if more than set lines
    breakLongLines?: number | string // auto break lines if longer than set words
    actions?: any[]
    styleOverrides?: TemplateStyleOverride[]
}

// output

export interface OutBackground {
    id?: ID
    path?: string
    name?: string
    type?: MediaType
    // video / player
    startAt?: number
    muted?: boolean
    loop?: boolean
    softLoop?: number
    // media
    filter?: string
    flipped?: boolean
    flippedY?: boolean
    blend?: string
    title?: string // player
    cameraGroup?: string // camera
    folderPath?: string // project media folder

    ignoreLayer?: boolean // foreground background type
}

export interface OutSlide {
    id: ID
    layout?: ID
    index?: number
    projectIndex?: number // only used to reference back to the project item index
    tempItems?: Item[]
    previousSlides?: Item[][]
    settings?: any // settings for temp (e.g. scripture background color)
    nextSlides?: Item[][]
    line?: number // styles limit lines
    revealCount?: number // reveal one by one line
    itemClickReveal?: boolean // reveal item on click
    // layout: ID ?
    name?: string // mostly used for PDFs
    type?: ShowType // mostly used for PDFs
    page?: number // PDF
    pages?: number // PDF
    screen?: { id: string; name?: string } // PPT

    translations?: number // scripture translations count (for style template)
    attributionString?: string // scripture custom attributionString
    customDynamicValues?: { [key: string]: string | [string, string][] } // used for scripture slides
}

export interface OutTransition {
    // action: string
    // slide?: number
    duration: number
    folderPath?: string
}

export interface SlideTimer {
    time: number
    paused: boolean
    sliderTimer: NodeJS.Timeout | null
    autoPlay: boolean
    max: number
    timer: any
    remaining?: number
    start?: number
    data?: string // used for project media folder loop
}

export interface Tag {
    name: string
    color: string
}

// types

export type ID = string
export type ItemType = "text" | "media" | "camera" | "timer" | "clock" | "button" | "events" | "weather" | "variable" | "web" | "icon" | "slide_tracker" | "visualizer" | "captions" | "metronome" | "current_output" | "chart" | "table" // "shape" | "video"
export type ShowType = "DIVIDER" | "show" | "image" | "video" | "audio" | "player" | "section" | "overlay" | "effect" | "pdf" | "ppt" | "screen" | "ndi" | "camera" | "folder" | "show_placeholder" // "private"
export type TransitionType = "none" | "blur" | "fade" | "crossfade" | "fly" | "scale" | "slide" | "spin"
export type MediaType = "media" | "video" | "image" | "effect" | "screen" | "ndi" | "camera" | "player" | "audio"
