import { Inject, Injectable } from '@angular/core'
import { ConfigService, PlatformService } from 'tabby-core'
import { TerminalDecorator, BaseTerminalTabComponent } from 'tabby-terminal'

import { LinkHandler } from './api'

@Injectable()
export class LinkHighlighterDecorator extends TerminalDecorator {
    constructor (
        private config: ConfigService,
        private platform: PlatformService,
        @Inject(LinkHandler) private handlers: LinkHandler[],
    ) {
        super()
    }

    attach (tab: BaseTerminalTabComponent): void {
        if (!(tab.frontend as any).xterm) {
            // not hterm
            return
        }

        for (const handler of this.handlers) {
            const getLink = async uri => handler.convert(uri, tab)
            const openLink = async uri => handler.handle(await getLink(uri), tab)

            ;(tab.frontend as any).xterm.registerLinkMatcher(
                handler.regex,
                (event: MouseEvent, uri: string) => {
                    if (!this.willHandleEvent(event)) {
                        return
                    }
                    openLink(uri)
                },
                {
                    priority: handler.priority,
                    validationCallback: async (uri: string, callback: (isValid: boolean) => void) => {
                        callback(await handler.verify(await handler.convert(uri, tab), tab))
                    },
                    willLinkActivate: (event: MouseEvent, uri: string) => {
                        if (event.button === 2) {
                            this.platform.popupContextMenu([
                                {
                                    click: () => openLink(uri),
                                    label: 'Open',
                                },
                                {
                                    click: async () => {
                                        this.platform.setClipboard({ text: await getLink(uri) })
                                    },
                                    label: 'Copy',
                                },
                            ])
                            return false
                        }
                        return this.willHandleEvent(event)
                    },
                }
            )
        }
    }

    private willHandleEvent (event: MouseEvent) {
        const modifier = this.config.store.clickableLinks.modifier
        return !modifier || event[modifier]
    }
}
