define([
        'knockout',
        'bluebird',
        'tools/all',
        'tnc/tnc-border',
        'tnc/tnc-margin',
        'widgets/transformation/ViewModel',
        'widgets/transformation/DeferredPromise',
        'widgets/transformation/TransformationPageItem'
    ],
    function() {
        'use strict';

        var Promise = require('bluebird');
        var allTools = require('tools/all');
        var arrays = allTools.arrays;
        var tools = allTools.tools;
        var log = tools.log;
        var jqTools = allTools.jqTools;
        var $new = jqTools.$new;
        var limitOpacity = tools.limitOpacity;
        var validate = allTools.validate;
        var getColor = validate.getColor;
        var getNum = validate.getNum;
        var TncBorder = require('tnc/tnc-border');
        var TncMargin = require('tnc/tnc-margin');
        var ViewModel = require('widgets/transformation/ViewModel');
        var ko = require("knockout");
        var DeferredPromise = require('widgets/transformation/DeferredPromise');
        var TransformationPageItem = require('widgets/transformation/TransformationPageItem');

        var sendPromisedEvent = function(target, eventName, eventData) {
            eventData.promise = 'Replace this string with a Promise to halt pageloading until the Promise is resolved.';
            var pageLoadEvent = new CustomEvent(eventName, {
                detail: eventData
            });
            target.dispatchEvent(pageLoadEvent);

            var result = Promise.resolve();
            if (eventData.promise && typeof eventData.promise.finally === 'function') {
                result = eventData.promise;
            }
            return result.catch(function() {}); // ignore errors
        };


        var TransformationPage = function(pageInfo, transformationData, resolveRelativeUrl) {
            var self = this;
            var templateData = transformationData.templateData;
            var parentSettings = transformationData.parentSettings;
            var widgetSettings = transformationData.widgetSettings;
            var domCollection = pageInfo.domCollection;
            pageInfo.page = self;

            var pageRenderedDeferredPromise = new DeferredPromise();
            self.rendered = pageRenderedDeferredPromise.promise;
            self.setRendered = function() {
                pageRenderedDeferredPromise.resolve();
            };

            var pageReadyToPlayDeferredPromise = new DeferredPromise();
            self.readyToPlay = pageReadyToPlayDeferredPromise.promise;
            self.setReadyToPlay = function() {
                pageReadyToPlayDeferredPromise.resolve();
            };

            var pageFinishedPlayingDeferredPromise = new DeferredPromise();
            self.finished = pageFinishedPlayingDeferredPromise.promise;
            self.setFinished = function() {
                pageFinishedPlayingDeferredPromise.resolve();
            };

            self.$ko = null;
            self.pageWindow = null;

            self.css = widgetSettings.css || '';
            //self.css = ' div.video-js { opacity: 0.01; } video { opacity: 0.01; } ' + self.css;
            self.css = ' div.video-js { visibility: hidden; } video { visibility: hidden; } ' + self.css;
            self.javascript = widgetSettings.javascript || '';
            self.params = widgetSettings.params || [];
            self.paramDisplayNames = widgetSettings.paramDisplayNames || [];


            self.manualPageEnd = false;

            //self.javascript = "" +
            //     "window.addEventListener('pageLoad', function(event) { console.log('pageLoad', event.detail); " +
            //     " event.detail.promise = Promise.delay(2000).then(function() {  console.log('waited 2 sec.'); }); " +
            //     "});" +
                // "window.addEventListener('pageStart', function(event) { console.log('pageStart', event.detail); " +
                // " event.detail.promise = Promise.delay(3000).then(function() {  console.log('waited 3 sec.'); }); " +
                // " event.detail.shouldWaitForVideo = true; event.detail.manualPageEnd = true; setTimeout(function() { console.log('customwait'); event.detail.setFinished() }, 30000); " +
                // "});";
            //     "window.addEventListener('pageEnd', function(event) { console.log('pageEnd', event.detail);" +
            //     " event.detail.promise = Promise.delay(4000).then(function() {  console.log('waited 4 sec.'); }); " +
            //     "});" +
            //     "window.addEventListener('itemStart', function(event) { console.log('itemStart', event.detail); " +
            //     " setTimeout(function() { console.log('finishing item');  event.detail.setFinished(); }, 20000) " +
            //     "});" +
            //     "window.addEventListener('itemEnd', function(event) { console.log('itemEnd', event.detail); });" +
            //     "";

            self.$element = $new('div', domCollection.$subcontainer);
            self.$element.addClass('knockoutPanelParent');
            self.$panel = $new('iframe', self.$element, {
                src: "ko-page.html",
                frameborder: "0"
            });

            self.$body = null;

            self.load = function() {
                return new Promise(function(resolve, reject) {

                    var backgroundColor = getColor(parentSettings.backgroundColor, 'transparent');
                    var border = new TncBorder(parentSettings.border || {});
                    var padding = new TncMargin(parentSettings.padding || {});

                    self.$element.css({
                        position: 'absolute',
                        width: '100%',
                        height: '100%',
                        top: '0px',
                        right: '0px',
                        bottom: '0px',
                        left: '0px',
                        overflow: 'hidden',
                        opacity: limitOpacity(0)
                    });

                    self.$panel.css({
                        position: 'absolute',
                        width: '100%',
                        height: '100%',
                        top: '0px',
                        right: '0px',
                        bottom: '0px',
                        left: '0px',
                        overflow: 'hidden'
                    });

                    self.$element.attr('page-index', pageInfo.pageIndex);

                    self.$panel.load(function() {
                        var w = tools.getWindowFromElement(self.$panel.contents().find("body"));
                        self.pageWindow = w;
                        w.params = self.params;
                        w.paramDisplayNames = self.paramDisplayNames;
                        w.Promise = Promise;

                        var d = w.document;
                        var b = d.body;
                        var h = d.head;

                        self.$body = $(b);

                        var s, t;
                        s = d.createElement('link');
                        s.setAttribute('rel', 'stylesheet');
                        s.setAttribute('href', 'theme/video/video-js.css');
                        h.appendChild(s);

                        s = d.createElement('script');
                        s.setAttribute('src', 'theme/video/video.min.js');
                        h.appendChild(s);

                        s = d.createElement('style');
                        t = d.createTextNode(self.css);
                        s.appendChild(t);
                        h.appendChild(s);

                        s = d.createElement('script');
                        t = d.createTextNode(self.javascript);
                        s.appendChild(t);
                        h.appendChild(s);

                        setTimeout(function() {
                            s = d.createElement('script');
                            s.setAttribute('src', 'theme/video/videojs-contrib-hls.min.js');
                            s.setAttribute('async', ''); // set async
                            h.appendChild(s);
                        }, 100);


                        var $knockoutPanel = $new('div', $(b));
                        $knockoutPanel.addClass('knockoutPanel');

                        var $panelContent = $new('div', $knockoutPanel);
                        $panelContent.addClass('knockoutPanelContent');
                        $panelContent.css({
                            //opacity: limitOpacity(0)
                        });

                        $panelContent.css({
                            'background-color': backgroundColor
                            /* , overflow:'hidden' */
                        });

                        border.applyBorder($panelContent);

                        self.$ko = $new('div', $panelContent);
                        self.$ko.addClass('knockoutContent');

                        self.$ko.css({
                            position: 'absolute',
                            width: 'auto',
                            height: 'auto',
                            overflow: 'hidden'
                        });
                        padding.applyMargin(self.$ko);

                        self.$ko.attr('data-bind', 'template: { afterRender: onAfterRender }');

                        var $inner = $new('div', self.$ko);
                        $inner.attr('data-bind', 'fadeVisible: pageReady');
                        $inner.append($(widgetSettings.layout));

                        resolve(self);
                    });
                });
            }

            self.preload = function() {
                return sendPromisedEvent(self.pageWindow, 'pageLoad', {
                    pageItems: pageInfo.pageItems
                }).finally(function() {

                    pageInfo.rawPageItems = pageInfo.pageItems.slice();
                    pageInfo.params = widgetSettings.params;
                    pageInfo.paramDisplayNames = widgetSettings.paramDisplayNames;

                    for (var i = 0; i < pageInfo.pageItems.length; i++) {
                        var item = pageInfo.pageItems[i];
                        var itemInfo = {
                            index: (pageInfo.pageIndex * pageInfo.pageSize) + i,
                            pageItemIndex: i,
                            pageIndex: pageInfo.pageIndex,
                            pageSize: pageInfo.pageSize,
                            pageDuration: getNum(parentSettings.duration, 10000)
                        };
                        pageInfo.pageItems[i] = new TransformationPageItem(item, itemInfo, self.pageWindow);
                    }

                    // Wait for all pageItems to preload
                    var p = [];
                    arrays.forEach(pageInfo.pageItems, function(item) {
                        if (typeof(item.preload) === 'function') {
                            p.push(item.preload());
                        }
                    });

                    return new Promise(function(resolve, reject) {
                        // Timeout preloading after 10000 ms
                        Promise.all(p).timeout(10000).finally(function() {
                            try {
                                var vm = new ViewModel(pageInfo, templateData, resolveRelativeUrl);
                                ko.applyBindings(vm, self.$ko[0]);
                            } catch(err) {
                                console.error(err);
                                reject(err);
                            }

                            self.rendered.timeout(2000).finally(function() {
                                vm.pageReadyToPlay(true);
                                self.setReadyToPlay();
                                log('page preloaded');
                                resolve();
                            });
                        });
                    });
                });
            };

            self.shouldWaitForVideo = true;

            var waitForVideos = function() {
                var p = [];
                $('video', self.$body).each(function(index, video) {
                    var videojsPlayer = null;

                    // var $v = $(video);
                    //
                    // var width = parseInt($v.attr('width'));
                    // var height = parseInt($v.attr('height'));
                    // $v.width(width);
                    // $v.height(height);

                    var videoPromise = new Promise(function(resolve, reject) {

                        var videoTimeout = setTimeout(function(){
                            var isPlaying = (videojsPlayer && videojsPlayer.currentTime() > 0);
                            if (!isPlaying)
                            {
                                resolve();
                            }
                        }, 7000);

                        if (self.pageWindow.videojs) {
                            videojsPlayer = self.pageWindow.videojs(video, {}, function() {
                                // ready
                                var $e = $(videojsPlayer.el());
                                $e.addClass('video-js');
                                $e.css({ visibility: 'hidden' });

                                setTimeout(function() {
                                    $e.css({ visibility: 'visible' });
                                    $('video', $e).css({ visibility: 'visible' });
                                }, 300);

                                var canPlay = function() {
                                    clearTimeout(videoTimeout);
                                };

                                videojsPlayer.on('loadedmetadata', canPlay);

                                videojsPlayer.on('error', function(err){
                                    resolve();
                                });

                                videojsPlayer.on("ended", function() {
                                    resolve();
                                });

                                videojsPlayer.play();
                            });
                        }

                    });

                    if(self.shouldWaitForVideo){
                        p.push(videoPromise);
                    }
                });

                return Promise.all(p).finally(function() {
                    console.log('all videos ended');
                });
            };

            self.play = function() {
                return sendPromisedEvent(self.pageWindow, 'pageStart', pageInfo).finally(function() {

                    // Promise to wait for the play() of all items
                    var allItemsFinished = Promise.all(pageInfo.pageItems.map(function(pageItem) {
                        return pageItem.play();
                    }));


                    // let op: geen return!
                    var pageFinished = self.finished
                        .finally(function() {
                            if (allItemsFinished.isPending()) {
                                arrays.forEach(pageInfo.pageItems, function(pageItem) {
                                    pageItem.setFinished();
                                });
                            }
                        });

                    // case1: (Wachten op alle items klaar AND Wachten op alle video's klaar)
                    // OF (items klaar en (geen video's of hoeft niet te wachten)
                    // OF gebruiker geeft aan dat case1 vervalt
                    // case2: OF self.finished aanroep (gebruiker geeft aan dat de pagina is afgelopen)

                    var case1 = Promise.all([allItemsFinished, waitForVideos()]);
                    var case2 = pageFinished;

                    var playEndedPromises = [case2]
                    if(!self.manualPageEnd) {
                        playEndedPromises.push(case1);
                    }

                    return Promise.any(playEndedPromises)
                        .finally(function() {
                            return sendPromisedEvent(self.pageWindow, 'pageEnd', self);
                        });
                });
            };
        };

        return TransformationPage;
    });
