import { Router, NavigationStart } from '@angular/router'
import { IApiService } from './services/ApiService/ApiService'
import { AnyFunction } from 'rpclibrary'
import { LoggerService } from './services/LoggerService/logger.service'
import { OnDestroy, Inject, PLATFORM_ID, Injector } from '@angular/core'
import { isPlatformBrowser } from '@angular/common'

export abstract class UpdatingComponent implements OnDestroy {

    private _uuid: string
    private _routerCancel: Function
    private _router: Router
    private _api: IApiService
    private _logger: LoggerService
    private platformId: Object

    constructor(
        injector: Injector
    ) {
        this._router = injector.get(Router)
        this._api = injector.get(IApiService)
        this._logger = injector.get(LoggerService)
        this.platformId = injector.get(PLATFORM_ID)
    }

    protected subscribe = (
        topic: string,
        callback: AnyFunction,
    ) => {
        if (!topic
        || topic === "null"
        || topic === "undefined"
        || !callback
        || !isPlatformBrowser(this.platformId)) 
        {
            return
        }

        const sub = this._router.events.subscribe(event => {
            if (event instanceof NavigationStart) {
                this.ngOnDestroy()
            }
        })
        this._routerCancel = () => { sub.unsubscribe() }
        this._api.get('PubSub').subscribe(topic, callback).then(uuid => {
            this._logger.collapsed(`New subscription ${topic}`, "table", {
                topic: topic,
                uuid: uuid
            })
            this._uuid = uuid
        }).catch(e => {
            this._logger.warn(`Subscribe for ${topic} failed, ${String(e)}`)
            delete this._uuid
        })
    }

    //Note angular may call this function several times
    ngOnDestroy() {
        if (this._uuid) {
            const id = this._uuid
            delete this._uuid
            this._api.get('PubSub').unsubscribe(id).then(() => {
                this._logger.log(`Unsubscribed from ${id}`)
            })
        }
        if (this._routerCancel) {
            try {
                this._routerCancel()
            } catch (e) {
                this._logger.warn(e)
            }
            delete this._routerCancel
        }
    }
}