/*
 * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* global window, document, tizen, console*/

/**
 * Main application module.
 * Handles application life cycle.
 *
 * @module app
 * @namespace app
 */

// make sure that "app" namespace is created
window.app = window.app || {};


//strict mode wrapper function
(function defineApp(app) {
    'use strict';

    /**
     * List of keys that are registered by default.
     *
     * @memberof app
     * @private
     * @const {object}
     */
    var DEFAULT_KEYS = {
            '13': 'Enter',
            '37': 'ArrowLeft',
            '38': 'ArrowUp',
            '39': 'ArrowRight',
            '40': 'ArrowDown'
        },

        /**
         * Name of CSS class used for displaying unsupported keys.
         *
         * @memberof app
         * @private
         * @const {string}
         */
        UNSUPPORTED_KEY_CLASS = 'unsupported-key',

        /**
         * Name of CSS class used for hiding objects.
         *
         * @memberof app
         * @private
         * @const {string}
         */
        INVISIBLE_KEY_CLASS = 'invisible',

        /**
         * Stores input device keys registered by sample.
         *
         * @memberof app
         * @private
         * @type {object}
         */
        keys = {},

        /**
         * Reference to the HTML element that contains name of
         * pressed button.
         *
         * @memberof app
         * @private
         * @type {HTMLElement}
         */
        buttonNameEl = null,

        /**
         * Reference to the HTML element that stores code of
         * pressed button.
         *
         * @memberof app
         * @private
         * @type {HTMLElement}
         */
        buttonCodeEl = null,

        /**
         * Reference to the HTML element that displays waiting message.
         *
         * @memberof app
         * @private
         * @type {HTMLElement}
         */
        waitingEl = null,

        /**
         * Reference to the HTML element that displays information
         * about pressed button.
         *
         * @memberof app
         * @private
         * @type {HTMLElement}
         */
        pressedStatusEl = null;

    /**
     * Registers all supported input device keys to receive DOM keyboard events
     * when they are pressed or released.
     * Additionally stores information about registered keys in object.
     *
     * @memberof app
     * @private
     */
    function registerKeys() {
        // register & save info about all supported keys
        var supportedKeys = tizen.tvinputdevice.getSupportedKeys(),
            i = 0;

        for (i = 0; i < supportedKeys.length; i += 1) {
            try {
                tizen.tvinputdevice.registerKey(supportedKeys[i].name);
            } catch (e) {
                console.error('Failed to register ' + supportedKeys[i].name, e);
            }
            keys[supportedKeys[i].code] = supportedKeys[i].name;
        }
    }

    /**
     * Handles remote key press event.
     * Checks whether pressed button is registered or not and displays
     * information about it on the UI.
     *
     * @memberof app
     * @private
     * @param {KeyboardEvent} e
     */
    function onKeyDownPress(e) {
        buttonNameEl.classList.remove(UNSUPPORTED_KEY_CLASS);

        if (keys.hasOwnProperty(e.keyCode)) {
            buttonNameEl.innerText = keys[e.keyCode];
        } else if (DEFAULT_KEYS.hasOwnProperty(e.keyCode)) {
            buttonNameEl.innerText = DEFAULT_KEYS[e.keyCode];
        } else {
            buttonNameEl.classList.add(UNSUPPORTED_KEY_CLASS);
            buttonNameEl.innerHTML = 'unsupported';
        }

        buttonCodeEl.innerText = e.keyCode;

        if (pressedStatusEl.classList.contains(INVISIBLE_KEY_CLASS)) {
            // hide waiting message
            waitingEl.classList.add(INVISIBLE_KEY_CLASS);
            // show information about pressed button
            pressedStatusEl.classList.remove(INVISIBLE_KEY_CLASS);
        }
    }

    /**
     * Closes the application.
     *
     * @memberof app
     * @public
     */
    app.exit = function exit() {
        try {
            tizen.application.getCurrentApplication().exit();
        } catch (error) {
            console.error('Application exit failed.', error);
        }
    };

    /**
     * Handles hardware key press event.
     * Closes the application if back key was pressed.
     *
     * @memberof app
     * @private
     * @param {Event} event
     */
    function onDeviceHardwareKeyPress(event) {
        if (event.keyName === 'back') {
            app.exit();
        }
    }

    /**
     * Registers event listeners.
     *
     * @memberof app
     * @private
     */
    function bindEvents() {
        document.addEventListener('tizenhwkey', onDeviceHardwareKeyPress);
        window.addEventListener('keydown', onKeyDownPress);
    }

    /**
     * Initializes application.
     * Assigns important HTML elements.
     * Triggers registering keys and binding events.
     *
     * @memberof app
     * @private
     */
    function init() {
        buttonNameEl = document.getElementById('button-name');
        buttonCodeEl = document.getElementById('button-code');
        waitingEl = document.getElementById('waiting');
        pressedStatusEl = document.getElementById('pressed-status');

        registerKeys();
        bindEvents();
    }

    window.addEventListener('load', init);

})(window.app);
