(function() {
const NODE_ID = 'QWERT_call_log';
const CONSOLE_NODE_ID = 'QWERT_console_log';

// Has this code already been injected?
if (document.getElementById(NODE_ID) != null) {
    return;
}

function appendNode(ID) {
    var node = document.createElement('p');
    var body = document.documentElement;
    node.id = ID;
    body.appendChild(node);
    node.textContent = "[]";
    return node;
}

/* some pages use custom JSON object(e.g. cnn).
   It can be incompatible with standard one.*/
var dummyFrame = document.createElement("iframe");
document.body.appendChild(dummyFrame);
json = dummyFrame.contentWindow.JSON;

var node = appendNode(NODE_ID);

var consoleLog = [];
var consoleNode = appendNode(CONSOLE_NODE_ID);
window.reportTestState = function(msg) {
    try {
        console.log(msg);
        consoleLog.push('' + msg);
        consoleNode.textContent = json.stringify(consoleLog);
    } catch (x) {
        console.log(x);
    }
};

var callLog = [];

function makeStub(name, callback) {
    function stringify(obj) {
        if (typeof(obj) == 'string')
            return obj;
        if (obj instanceof Function)
            return String(obj);
        if (!(obj instanceof Object))
            return json.stringify(obj);
        var dump = {};
        for (var i in obj) {
            if (obj.hasOwnProperty(i))
                dump[i] = stringify(obj[i]);
        }
        return dump;
    }
    return function () {
        try {
            var args = [];
            for (var i = 0; i < arguments.length; i++) {
                args.push(stringify(arguments[i]));
            }

            callLog.push({ func: name, args: args});

            node.textContent = json.stringify(callLog);
            if (callback)
                return callback.apply(window, arguments);
        } catch (x) {
            console.log(x);
        }
    };
}

window.unsafeWindow = window;
var callbacks = {};

var Unity = {
    _invoke: function (funcName, id) {
        if (id) {
            callbacks[funcName + id]();
        } else {
            callbacks[funcName]();
        }
    },

    init: makeStub('Unity.init', function (props) {
        if (props.onInit)
            props.onInit();
    }),

    acceptData: makeStub('Unity.acceptData', function(mimes, callback) {
        callbacks['Unity.acceptData'] = callback;
    }),

    addAction: makeStub('Unity.addAction', function (name, callback) {
        callbacks['Unity.addAction' + name] = callback;
    }),

    MediaPlayer: {
        init: makeStub('Unity.MediaPlayer.init'),
        onPlayPause: makeStub('Unity.MediaPlayer.onPlayPause', function (callback) {
            callbacks['Unity.MediaPlayer.onPlayPause'] = callback;
        }),
        onPrevious: makeStub('Unity.MediaPlayer.onPrevious', function (callback) {
            callbacks['Unity.MediaPlayer.onPrevious'] = callback;
        }),
        onNext: makeStub('Unity.MediaPlayer.onNext', function (callback) {
            callbacks['Unity.MediaPlayer.onNext'] = callback;
        }),
        setTrack: makeStub('Unity.MediaPlayer.setTrack'),

      setCanGoNext: makeStub('Unity.MediaPlayer.setCanGoNext'),

      setCanGoPrevious: makeStub('Unity.MediaPlayer.setCanGoPrevious'),

      setCanPlay: makeStub('Unity.MediaPlayer.setCanPlay'),

      setCanPause: makeStub('Unity.MediaPlayer.setCanPause'),

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

    Launcher: {
        setCount: makeStub('Unity.Launcher.setCount'),
        clearCount: makeStub('Unity.Launcher.clearCount'),
        setProgress: makeStub('Unity.Launcher.setProgress'),
        clearProgress: makeStub('Unity.Launcher.clearProgress'),
        setUrgent: makeStub('Unity.Launcher.setUrgent'),
        removeActions: makeStub('Unity.Launcher.removeActions'),
        addAction: makeStub('Unity.Launcher.addAction', function (name, callback) {
            callbacks['Unity.Launche.addAction' + name] = callback;
        })
    },

    Notification: {
        showNotification: makeStub('Unity.Notification.showNotification')
    },

    MessagingIndicator: {
        addAction: makeStub('Unity.MessagingIndicator.addAction', function (name, callback) {
            callbacks['MessagingIndicator' + name] = callback;
        }),
        clearIndicator: makeStub('Unity.MessagingIndicator.clearIndicator'),
        clearIndicators: makeStub('Unity.MessagingIndicator.clearIndicators'),
        showIndicator: makeStub('Unity.MessagingIndicator.showIndicator')
    }
};

function defineGetterSetter(obj, objName, propertyName) {
    var value = true;
    obj['set' + propertyName] = function(val) {
        callLog.push({ func: objName + '.' + propertyName, args: [String(val)] });
        node.textContent = json.stringify(callLog);
        value = val;
    };
    obj['get' + propertyName] = function(callback) {
        if (callback) {
            callback(value);
        }
    };
}
defineGetterSetter(Unity.MediaPlayer, 'Unity.MediaPlayer', 'PlaybackState');

window.external = {
};

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

})();
