define(['browser', 'dom', 'css!./viewcontainer-lite'], function (browser, dom) {
    'use strict';

    var mainAnimatedPages = document.querySelector('.mainAnimatedPages');
    var allPages = [];
    var currentUrls = [];
    var pageContainerCount = 3;
    var selectedPageIndex = -1;

    function enableAnimation() {

        // too slow
        if (browser.tv) {
            return false;
        }
        if (navigator.userAgent.toLowerCase().indexOf('embytheaterpi') !== -1) {
            return false;
        }

        return browser.supportsCssAnimation();
    }

    function loadView(options) {

        if (options.cancel) {
            return;
        }

        cancelActiveAnimations();

        var selected = selectedPageIndex;
        var previousAnimatable = selected === -1 ? null : allPages[selected];
        var pageIndex = selected + 1;

        if (pageIndex >= pageContainerCount) {
            pageIndex = 0;
        }

        var view = document.createElement('div');

        if (options.type) {
            view.setAttribute('data-type', options.type);
        }
        view.innerHTML = options.view;

        var currentPage = allPages[pageIndex];
        var animatable = view;

        view.classList.add('mainAnimatedPage');

        if (currentPage) {
            triggerDestroy(currentPage);
            mainAnimatedPages.replaceChild(view, currentPage);
        } else {
            mainAnimatedPages.appendChild(view);
        }

        allPages[pageIndex] = view;

        if (onBeforeChange) {
            onBeforeChange(view, false, options);
        }

        beforeAnimate(allPages, pageIndex, selected);

        // animate here
        return animate(animatable, previousAnimatable, options.transition, options.isBack).then(function () {

            selectedPageIndex = pageIndex;
            currentUrls[pageIndex] = options.url;
            if (!options.cancel && previousAnimatable) {
                afterAnimate(allPages, pageIndex);
            }

            return view;
        });
    }

    function beforeAnimate(allPages, newPageIndex, oldPageIndex) {
        for (var i = 0, length = allPages.length; i < length; i++) {
            if (newPageIndex === i || oldPageIndex === i) {
                //allPages[i].classList.remove('hide');
            } else {
                allPages[i].classList.add('hide');
            }
        }
    }

    function afterAnimate(allPages, newPageIndex) {
        for (var i = 0, length = allPages.length; i < length; i++) {
            if (newPageIndex === i) {
                //allPages[i].classList.remove('hide');
            } else {
                allPages[i].classList.add('hide');
            }
        }
    }

    function animate(newAnimatedPage, oldAnimatedPage, transition, isBack) {

        if (enableAnimation() && oldAnimatedPage) {
            if (transition === 'slide') {
                return slide(newAnimatedPage, oldAnimatedPage, transition, isBack);
            } else if (transition === 'fade') {
                return fade(newAnimatedPage, oldAnimatedPage, transition, isBack);
            }
        }

        return Promise.resolve();
    }

    function slide(newAnimatedPage, oldAnimatedPage, transition, isBack) {

        return new Promise(function (resolve, reject) {

            var duration = 450;

            var animations = [];

            if (oldAnimatedPage) {
                if (isBack) {
                    setAnimation(oldAnimatedPage, 'view-slideright-r ' + duration + 'ms ease-out normal both');
                } else {
                    setAnimation(oldAnimatedPage, 'view-slideleft-r ' + duration + 'ms ease-out normal both');
                }
                animations.push(oldAnimatedPage);
            }

            if (isBack) {
                setAnimation(newAnimatedPage, 'view-slideright ' + duration + 'ms ease-out normal both');
            } else {
                setAnimation(newAnimatedPage, 'view-slideleft ' + duration + 'ms ease-out normal both');
            }
            animations.push(newAnimatedPage);

            currentAnimations = animations;

            var onAnimationComplete = function () {
                dom.removeEventListener(newAnimatedPage, dom.whichAnimationEvent(), onAnimationComplete, {
                    once: true
                });
                resolve();
            };

            dom.addEventListener(newAnimatedPage, dom.whichAnimationEvent(), onAnimationComplete, {
                once: true
            });
        });
    }

    function fade(newAnimatedPage, oldAnimatedPage, transition, isBack) {

        return new Promise(function (resolve, reject) {

            var duration = 400;
            var animations = [];

            if (oldAnimatedPage) {
                setAnimation(oldAnimatedPage, 'view-fadeout ' + duration + 'ms ease-out normal both');
                animations.push(oldAnimatedPage);
            }

            setAnimation(newAnimatedPage, 'view-fadein ' + duration + 'ms ease-in normal both');
            animations.push(newAnimatedPage);

            currentAnimations = animations;

            var onAnimationComplete = function () {
                dom.removeEventListener(newAnimatedPage, dom.whichAnimationEvent(), onAnimationComplete, {
                    once: true
                });
                resolve();
            };

            dom.addEventListener(newAnimatedPage, dom.whichAnimationEvent(), onAnimationComplete, {
                once: true
            });
        });
    }

    function setAnimation(elem, value) {

        requestAnimationFrame(function () {
            elem.style.animation = value;
        });
    }

    var currentAnimations = [];
    function cancelActiveAnimations() {

        var animations = currentAnimations;
        for (var i = 0, length = animations.length; i < length; i++) {
            animations[i].animation = 'none';
        }
    }

    var onBeforeChange;
    function setOnBeforeChange(fn) {
        onBeforeChange = fn;
    }

    function tryRestoreView(options) {

        var url = options.url;
        var index = currentUrls.indexOf(url);

        if (index !== -1) {

            var animatable = allPages[index];
            var view = animatable;

            if (view) {

                if (options.cancel) {
                    return;
                }

                cancelActiveAnimations();

                var selected = selectedPageIndex;
                var previousAnimatable = selected === -1 ? null : allPages[selected];

                if (onBeforeChange) {
                    onBeforeChange(view, true, options);
                }

                beforeAnimate(allPages, index, selected);

                animatable.classList.remove('hide');

                return animate(animatable, previousAnimatable, options.transition, options.isBack).then(function () {

                    selectedPageIndex = index;
                    if (!options.cancel && previousAnimatable) {
                        afterAnimate(allPages, index);
                    }
                    return view;
                });
            }
        }

        return Promise.reject();
    }

    function triggerDestroy(view) {

        view.dispatchEvent(new CustomEvent('viewdestroy', {
            cancelable: false
        }));
    }

    function reset() {

        allPages = [];
        currentUrls = [];
        mainAnimatedPages.innerHTML = '';
        selectedPageIndex = -1;
    }

    return {
        loadView: loadView,
        tryRestoreView: tryRestoreView,
        reset: reset,
        setOnBeforeChange: setOnBeforeChange
    };
});