import { Subject } from 'rxjs'
import * as semverCompare from 'semver/functions/compare-loose'
import { HttpClient } from '@angular/common/http'
import { Component, ElementRef, ViewChild } from '@angular/core'
import { InstanceInfo, Version } from '../api'
import { faCoffee, faDownload, faSignInAlt } from '@fortawesome/free-solid-svg-icons'
import { faGithub } from '@fortawesome/free-brands-svg-icons'
import { ActivatedRoute } from '@angular/router'
import { CommonService } from '../services/common.service'


class DemoConnector {
    constructor (
        targetWindow: Window,
        private commonService: CommonService,
        private version: Version,
    ) {
        this.getDistURL().then(distURL => {
            targetWindow['tabbyWebDemoDataPath'] = `${distURL}/${version.version}/tabby-web-demo/data`
        })
    }

    async loadConfig (): Promise<string> {
        return `{
            recoverTabs: false,
            web: {
                preventAccidentalTabClosure: false,
            },
        }`
    }

    // eslint-disable-next-line @typescript-eslint/no-empty-function
    async saveConfig (_content: string): Promise<void> { }

    getAppVersion (): string {
        return this.version.version
    }

    async getDistURL (): Promise<string> {
        return await this.commonService.backendURL$ + '/app-dist'
    }

    getPluginsToLoad (): string[] {
        return [
            'tabby-core',
            'tabby-settings',
            'tabby-terminal',
            'tabby-community-color-schemes',
            'tabby-ssh',
            'tabby-telnet',
            'tabby-web',
            'tabby-web-demo',
        ]
    }

    createSocket () {
        return new DemoSocketProxy()
    }
}


export class DemoSocketProxy {
    connect$ = new Subject<void>()
    data$ = new Subject<Buffer>()
    error$ = new Subject<Buffer>()
    close$ = new Subject<Buffer>()

    async connect (options) {
        this.error$.next(new Error('This web demo can\'t actually access Internet, but feel free to download the release and try it out!'))
    }
}


@Component({
    selector: 'home',
    templateUrl: './home.component.pug',
    styleUrls: ['./home.component.scss'],
})
export class HomeComponent {
    @ViewChild('iframe') iframe: ElementRef
    connector: DemoConnector
    githubURL = 'https://github.com/Eugeny/tabby'
    releaseURL = `${this.githubURL}/releases/latest`
    donationURL = 'https://ko-fi.com/eugeny'

    _logo = require('../assets/logo.svg')
    _downloadIcon = faDownload
    _loginIcon = faSignInAlt
    _githubIcon = faGithub
    _donateIcon = faCoffee

    screenshots = {
        window: require('../assets/screenshots/window.png'),
        tabs: require('../assets/screenshots/tabs.png'),
        ssh: require('../assets/screenshots/ssh.png'),
        serial: require('../assets/screenshots/serial.png'),
        win: require('../assets/screenshots/win.png'),
    }

    instanceInfo: InstanceInfo

    constructor (
        private http: HttpClient,
        private commonService: CommonService,
        route: ActivatedRoute,
    ) {
        window.addEventListener('message', this.connectorRequestHandler)
        this.instanceInfo = route.snapshot.data.instanceInfo
    }

    // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
    connectorRequestHandler = event => {
        if (event.data === 'request-connector') {
            this.iframe.nativeElement.contentWindow['__connector__'] = this.connector
            this.iframe.nativeElement.contentWindow.postMessage('connector-ready', '*')
        }
    }

    async ngAfterViewInit (): Promise<void> {
        const versions = await this.http.get('/api/1/versions').toPromise()
        versions.sort((a, b) => -semverCompare(a.version, b.version))
        this.connector = new DemoConnector(this.iframe.nativeElement.contentWindow, this.commonService, versions[0])
        this.iframe.nativeElement.src = '/terminal.html'
    }

    ngOnDestroy (): void {
        window.removeEventListener('message', this.connectorRequestHandler)
    }
}