src/app/bootstrap.ts

Summary

Maintainability
B
4 hrs
Test Coverage
import Store from "../_utilities/storage.utility";
import * as $ from 'jquery';
import { DeviceConfig } from "../_models";
import Application from "./app-manager";
import LogHelper from '../_helpers/log.helper';
import { Registry } from '../libs';
import { ConfigHelper } from '../_helpers';

declare let window: any;

export default class Bootstrap {

    public log: LogHelper;
    readonly config;
    private store;
    protected broadcastVideo: any;
    protected appManager: any;
    protected configObject: any;
    protected moduleRegistry;
    protected deviceParams: DeviceConfig = new DeviceConfig();

    constructor(config, modules) {
        window.$ = $;

        this.config = config;
        this.store = Store;
        this.moduleRegistry = new Registry(modules);
        this.log = new LogHelper(config);

        const self = this;
        this.handleBody();
        this.cacheConfig(config);
        this.preFlight(function () {
            self.prepareApps();
        });
    }

    private cacheConfig(config): void {
        config = ConfigHelper.prepare(config);
        try {
            Store.set('config', config);
        } catch (e) {
            this.log.error('error caching config');
        }
    }

    private handleModules(modules: any[]): any[] {
        modules.forEach((item) => {
            item['_constructor'] = this.moduleRegistry.getItem(item.type);
        });
        return modules;
    }

    private prepareApps(): void {
        const applications = this.config.applications;
        const self = this;

        // Verbose events
        if (this.config.verbose) {
            $("body").append('<div id="logs" />');
            $(document).on('keydown', function (e) {
                if ($('#logs p').length > 19) {
                    $('#logs p:first').remove();
                }
                $('#logs').append('<p>key event: ' + e.key + '; which is: ' + e.which + '</p>');
            });
        }

        for (let i in applications) {
            if (typeof applications.hasOwnProperty(i) !== 'undefined') {
                applications[i].modules = this.handleModules(applications[i].modules);
                self.initializeApp(applications[i]);
            }
        }
    }

    private initializeApp(app: object): void {
        new Application(app, this.config, this);
    }

    private handleBody(): void {
        const self = this;
        const bodyClass: string = (self.config.hd ? 'hd-' : 'sd-') + self.config.resolution;
        $("body").addClass(bodyClass);
    }

    private preFlight(callback): void {
        const self = this;
        window.onload = (function () {
            const $$video: any = self.broadcastVideo = document.getElementById("broadcastvideo");
            const $$appManager: any = self.appManager = document.getElementById("appmgr");
            self.configObject = document.getElementById("oipfcfg");

            // self.getDeviceParams(self.broadcastVideo);
            // self.handleVideoSize(self.broadcastVideo);

            // Show application
            let $app: any;
            try {
                try {
                    $app = $$appManager.getOwnerApplication(document);
                    $app.show();
                } catch (error) {
                    self.log.error('application show() failed!');
                    // console.error('Application show() failed!', error);
                }
                try {
                    $app.activate();
                    self.log.info('application activate()');
                } catch (error) {
                    /* this is for HbbTV 0.5 backwards-compliance. It will throw an ignored exception on HbbTV 1.x devices, which is fine */
                    // self.log.error('application activate() for HbbTV 0.5 failed');
                }
            } catch (error) {
                self.log.error('problem initializing application');
                // console.error('Problem initializing application', error);
            }

            // if ($$video.currentChannel) {
            try {
                $$video.setFullScreen(true);
            } catch (e) {
                // console.error('Error switching to fullscreen', e);
                self.log.error('Cannot switch to fullscreen');
            }
            try {
                $$video.bindToCurrentChannel();
            } catch (e) {
                self.log.error('cannot bind to current channel');
                // console.error('Error bind element to current channel', e);
            }
            // } else {
            //     self.log.error('cannot determine current channel');
            //     // console.error('Cannot determine current channel.');
            // }

            self.setKeySet(0x1 + 0x2 + 0x4 + 0x8); // Colors
            callback();
        });
    }

    public setKeySet(mask): void {
        let elemcfg, app;

        try {
            elemcfg = document.getElementById('oipfcfg');
            // for HbbTV 0.5:
            elemcfg.keyset.value = mask;
        } catch (e) {
            /* In newer versions of HbbTV keyset.value is read-only, therefore this method throws an exception */
            // ignore
        }
        try {
            elemcfg = document.getElementById('oipfcfg');
            elemcfg.keyset.setValue(mask);
        } catch (e) {
            /* In newer versions of HbbTV keyset.setValue only works on privateData of application, therefore this method throws an exception */
            // ignore
        }
        // for HbbTV 1.0:
        try {
            app = this.appManager.getOwnerApplication(document);
            app.privateData.keyset.setValue(mask);
        } catch (e) {
            this.log.error('set keyset value failed [for HbbTV 1.0]');
        }
    }

    handleVideoSize(broadCastVideo): void {
        if (broadCastVideo && broadCastVideo.style) {
            broadCastVideo.style.display = 'block';
            broadCastVideo.style.left = '0px';
            broadCastVideo.style.top = '0px';
            broadCastVideo.style.width = this.config.hd ? ((this.config.resolution * 16) / 9) + 'px' : ((this.config.resolution * 4) / 3) + 'px';
            broadCastVideo.style.height = this.config.resolution + 'px';
        }
    }

    getDeviceParams(broadcastObject): void {
        if (broadcastObject && typeof broadcastObject.currentChannel !== 'undefined' && broadcastObject.currentChannel) {
            try {
                this.deviceParams.channelList = broadcastObject.getChannelConfig().channelList;
                this.deviceParams.channelName = broadcastObject.currentChannel.name;
                this.deviceParams.channelCCID = broadcastObject.currentChannel.ccid;
                this.deviceParams.channelDescription = broadcastObject.currentChannel.description;
                this.deviceParams.channelONID = broadcastObject.currentChannel.onid;
                this.deviceParams.channelSID = broadcastObject.currentChannel.sid;
                this.deviceParams.channelTSID = broadcastObject.currentChannel.tsid;
            } catch (e) {
                console.error('problem mapping current channel data to deviceParams: 2', e);
            }
        } else {
            console.error('problem mapping current channel data to deviceParams: 1');
        }
        this.deviceParams.cookieEnabled = navigator.cookieEnabled;
        this.deviceParams.userAgent = navigator.userAgent;
        this.deviceParams.viewportWidth = $(window).width();
        this.deviceParams.viewportHeight = $(window).height();
        // Cache device params
        this.storeDeviceParams(this.deviceParams);
    }

    private storeDeviceParams(deviceParams): void {
        Store.set('params', deviceParams);
    }

    public destroy(layout?: string): void {
        if (this.config.exitMethod === 'hide') {
            try {
                this.appManager.hide();
            } catch (e) {
                console.error('error hiding application');
            }
        } else {
            this.setKeySet(0x1 + 0x2 + 0x4 + 0x8);
            try {
                this.appManager.destroyApplication();
            } catch (e) {
                console.error('cannot destroy application, force-hiding app');
                document.getElementById('app').style.display = 'none';
            }
        }
    }
}