define(['bluebird', 'jquery'], function() {
    var Promise = require('bluebird');
    var $ = require('jquery');

    var getWindowFromElement = function(element) {
        var $e = $(element);
        var e = $e[0];
        var doc = e.ownerDocument;
        var win = doc.defaultView || doc.parentWindow;
        return win;
    };

    var defer = function() {
        var res, rej;
        var promise = new Promise(function(resolve, reject) {
            res = resolve;
            rej = reject;
        });
        return {
            promise: promise,
            resolve: res,
            reject: rej,
        };
    };

    var ParentWidget = function($parent, settings) {
        this.init($parent, settings);
    };

    ParentWidget.prototype.init = function($parent, settings) {
        var self = this;
        self.$parent = $parent;
        self.window = getWindowFromElement($parent);
        self.$frame = $('<iframe class="widget" src="widget.html"></iframe>');
        self.$parent.append(this.$frame);

        self.settings = settings;
        self.deferInitialized = defer();
        self.deferLoaded = defer();
        self.deferPlayed = defer();
        self.lastMessage = new Date(); // for timeout and hang calculation

        self.window.addEventListener("message", function(event) {
            return self.onMessage(event);
        }, false);
    };

    ParentWidget.prototype.sendMessage = function(message) {
        var self = this;
        var str = JSON.stringify(message);
        //console.log('Parent: Send:', str);
        self.$frame[0].contentWindow.postMessage(str, '*');
    };

    ParentWidget.prototype.onMessage = function(event) {
        var self = this;
        if (event.source === self.$frame[0].contentWindow) {
            try {
                //console.log('Parent: Received:', event.data);
                self.lastMessage = new Date(); // widget is still busy sending messages to us
                var data = JSON.parse(event.data);
                switch (data.widgetEvent) {
                    case 'initialized':
                        self.deferInitialized.resolve();
                        break;
                    case 'loaded':
                        self.deferInitialized.resolve();
                        self.deferLoaded.resolve();
                        break;
                    case 'played':
                        self.deferInitialized.resolve();
                        self.deferLoaded.resolve();
                        self.deferPlayed.resolve();
                        break;
                }
            } catch (e) {
                // !ignore any json errors
            }
        }
    };

    ParentWidget.prototype.load = function() {
        var self = this;
        return self.deferInitialized.promise.timeout(10000)
            .then(function() {
                self.sendMessage({
                    widgetAction: 'load',
                    settings: self.settings
                });
                return self.deferLoaded.promise;
            })
            .catch(Promise.TimeoutError, function(e) {
                console.log("Could not load widget in 10000ms");
                return Promise.reject();
            });
    };

    ParentWidget.prototype.play = function() {
        var self = this;
        self.sendMessage({
            widgetAction: 'play',
            settings: self.settings
        });
        return self.deferPlayed.promise;
    };

    return ParentWidget;
});
