// ==UserScript==
// @inject_in_main_world
// ==/UserScript==

/*
 * Copyright 2013 Canonical Ltd.
 *
 * This file is part of unity-webapps-qml.
 *
 * unity-webapps-qml is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 3.
 *
 * unity-webapps-qml is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

(function () {

    if (window.self !== window.top) {
        return;
    }

    // Acknowledge that the API has been fully injected
    var sendApiCreatedAcknowledgeEvent = function () {
        var e = document.createEvent ("Events");
        e.initEvent ("ubuntu-webapps-api-ready", false, false);
        document.dispatchEvent (e);
    };

    //@include UnityWebAppsUtils.js
    //@include ./bindings/alarm-api/client/alarm-api.js
    //@include ./bindings/content-hub/client/content-hub.js
    //@include ./bindings/online-accounts/client/online-accounts.js
    //@include ./bindings/runtime-api/client/runtime-api.js
    //@include ./bindings/download-manager/client/download-api.js
    //@include ./bindings/tools/client/tools.js
    //@include ./common/js/unity-backend-messaging-proxy.js
    //@include ./common/js/unity-binding-proxy.js
    //@include ./common/js/unity-binding-bridge.js

    var apiBuilder = function(backend) {

        //@include ./common/js/api-sanitizer.js

        var api = {
            init: function(props) {
                checkString(props.name, false);
                checkString(props.iconUrl, true);
                checkString(props.domain, true);
                checkString(props.login, true);
                checkString(props.mimeTypes, true);
                checkString(props.homepage, true);

                if (props.homepage && !/^(http|https|file):\/\//.test(props.homepage)) {
                    throw new TypeError("incorrect argument");
                }

                if (window.location.protocol !== 'file:')
                    props.__unity_webapps_hidden = {
                        hostname: window.location.hostname,
                        url: window.location.href
                    };
                else
                    props.__unity_webapps_hidden = {local: true};

                backend.call("init", [props]);
            },

            /**
             *
             * @method acceptData
             * @param mimeType {String}
             * @param callback {Function}
             */
            acceptData: createArgumentsSanitizer (backend,
                                                 [{ array: { element: { str: true } } }, { type: Function, js: true }],
                                                 'acceptData'),

            /**
             *
             * @param name {String}
             * @param callback {Function}
             */
            addAction: createArgumentsSanitizer (backend,
                                                [{ str: true }, { type: Function, argAsCallbackId: 0 }]
                                                , 'addAction'),

            /**
             *
             * @param name {String}
             */
            clearAction: createArgumentsSanitizer (backend, [{ str: true }], 'clearAction'),

            /**
             *
             */
            clearActions: createArgumentsSanitizer (backend, [], 'clearActions'),

            /**
             */
            launchEmbeddedUI: function(name, callback, params) {
                backend.call('launchEmbeddedUI', [name, callback, params]);
            },

            /**
             *
             * MediaPlayer API
             *
             */
            MediaPlayer: {
                init: function() {},

                /**
                 *
                 * @param callback {Function}
                 */
                onPlayPause: createArgumentsSanitizer (backend, [{ type: Function, allowNull: true }, { dummy: true }]
                                                       , 'MediaPlayer.onPlayPause'),

                /**
                 *
                 * @param callback {Function}
                 */
                onPrevious: createArgumentsSanitizer (backend, [{ type: Function, allowNull: true }, { dummy: true }]
                                                      , 'MediaPlayer.onPrevious'),

                /**
                 *
                 * @param callback {Function}
                 */
                onNext: createArgumentsSanitizer (backend, [{ type: Function, allowNull: true }, { dummy: true }]
                                                  , 'MediaPlayer.onNext'),

                /**
                 *
                 * @param callback {Function}
                 */
                setTrack: createArgumentsSanitizer(backend, [{ obj: { artist: { str: true, place: 0, allowNull: true },
                                                              album: { str: true, place: 1, allowNull: true },
                                                              title: { str: true, place: 2 },
                                                              artLocation: { str: true, place: 3, allowNull: true } } }]
                                                   , 'MediaPlayer.setTrack'),

                /**
                 *
                 * @param callback {Function}
                 */
                setCanGoNext: createArgumentsSanitizer (backend, [{ number: true }], 'MediaPlayer.setCanGoNext'),

                /**
                 *
                 * @param callback {Function}
                 */
                setCanGoPrevious: createArgumentsSanitizer (backend, [{ number: true }], 'MediaPlayer.setCanGoPrevious'),

                /**
                 *
                 * @param callback {Function}
                 */
                setCanPlay: createArgumentsSanitizer (backend, [{ number: true }], 'MediaPlayer.setCanPlay'),

                /**
                 *
                 * @param callback {Function}
                 */
                setCanPause: createArgumentsSanitizer (backend, [{ number: true }], 'MediaPlayer.setCanPause'),

                /**
                 *
                 * @param callback {Function}
                 */
                setPlaybackState: createArgumentsSanitizer (backend, [{ number: true }], 'MediaPlayer.setPlaybackState'),

                /**
                 *
                 * @param callback {Function}
                 */
                getPlaybackState: createArgumentsSanitizer (backend, [{ type: Function }], 'MediaPlayer.getPlaybackState'),

                PlaybackState: {PLAYING: 0, PAUSED:1},

                /**
                 * @private
                 */
                __get: createArgumentsSanitizer(backend, [{ str: true }, { type: Function, argAsCallbackId: 0 }], 'MediaPlayer.__get')
            },

            Notification: {
               /**
                *
                * @param callback {Function}
                */
                showNotification: createArgumentsSanitizer (backend, [{ str: true }, { str: true }, { str: true, allowNull: true }]
                                                           , 'Notification.showNotification')
            },

            Launcher: {
                /**
                 *
                 * @param callback {Function}
                 */
                setCount: createArgumentsSanitizer (backend, [{ number: true }], 'Launcher.setCount'),

                /**
                 *
                 * @param callback {Function}
                 */
                clearCount: createArgumentsSanitizer (backend, [], 'Launcher.clearCount'),

                /**
                 *
                 * @param callback {Function}
                 */
                setProgress: createArgumentsSanitizer (backend, [{ number: true }], 'Launcher.setProgress'),

                /**
                 *
                 * @param callback {Function}
                 */
                clearProgress: createArgumentsSanitizer (backend, [], 'Launcher.clearProgress'),

                /**
                 *
                 * @param callback {Function}
                 */
                setUrgent: createArgumentsSanitizer (backend, [], 'Launcher.setUrgent'),

                /**
                 *
                 * @param callback {Function}
                 */
                addAction: function(arg1, arg2) {
                    if (typeof(arg2) === 'string')
                        backend.call('Launcher.addStaticAction', [arg1, arg2]);
                    else
                        backend.call('Launcher.addAction', [arg1, arg2]);
                },

                /**
                 *
                 * @param callback {Function}
                 */
                removeAction: createArgumentsSanitizer (backend, [{ str: true }], 'Launcher.removeAction'),

                /**
                 *
                 * @private
                 */
                removeActions: createArgumentsSanitizer (backend, [], 'Launcher.removeActions'),

                 /**
                  *
                  * @private
                  */
                __get: createArgumentsSanitizer (backend, [{ str: true }, { type: Function, argAsCallbackId: 0 }]
                                                , 'Launcher.__get')
            },
            MessagingIndicator: {
                /**
                 *
                 * @private
                 */
                addAction: createArgumentsSanitizer (backend, [{ str: true }, { type: Function, argAsCallbackId: 0 }, { dummy: true }]
                                                    , 'MessagingIndicator.addAction'),

                /**
                 *
                 * @private
                 */
                showIndicator: function(name, properties) {
                    backend.call('MessagingIndicator.showIndicator', [name, properties]);
                },

                /**
                 *
                 * @private
                 */
                clearIndicator: createArgumentsSanitizer (backend, [{ str: true }], 'MessagingIndicator.clearIndicator'),

                /**
                 *
                 * @private
                 */
                clearIndicators: createArgumentsSanitizer (backend, [], 'MessagingIndicator.clearIndicators'),
            },

            OnlineAccounts: createOnlineAccountsApi(backend),
            AlarmApi: createAlarmApi(backend),
            ContentHub: createContentHubApi(backend),
            RuntimeApi: createRuntimeApi(backend),
            DownloadApi: createDownloadApi(backend),
            ToolsApi: createToolsApi(backend)
        };

        return api;
    };

    var apiBridge = new UnityBindingBridge(makeCallbackManager(),
        createMessagingProxyForCurrentWebRuntime());

    var api = apiBuilder (apiBridge);

    apiBridge.setBindingApi(api);

    if (!window.external)
        window.external = {};

    window.external.getUnityObject = function (version) {
        return api;
    };

    sendApiCreatedAcknowledgeEvent();

    unsafeWindow = window;
}) ();

