'use strict';

Ox.load(function() {

    var app = {
        $ui: {},
        animate: function() {
            var home = app.url.get().page == '';
            app.state.animating = true;
            if (home) {
                app.$ui.logo.attr({
                    src: app.getSRC('logo')
                });
                app.$ui.screen.show();
                app.$ui.label.show();
                app.$ui.menu.options({value: ''}).show();
            } else {
                app.$ui.menu.options({value: app.user.page});
            }
            app.$ui.panel.find('.OxButtonGroup').css({opacity: 0});
            [
                'screen', 'logo', 'label', 'menu', 'switch'
            ].forEach(function(element) {
                app.$ui[element].stop().animate(
                    app.getCSS(element),
                    1000,
                    element == 'screen' ? function() {
                        if (!home) {
                            app.$ui.logo.attr({
                                src: app.getSRC('logo')
                            });
                            app.$ui.panel.find('.OxButtonGroup').css({opacity: 1});
                            app.$ui.screen.hide();
                            app.$ui.label.hide();
                            app.$ui.menu.hide().options({value: ''});
                        }
                        app.state.animating = false;
                    } : void 0
                );
            });
        },
        data: {
            html: {},
            pages: [
                {id: 'about', title: 'About'},
                {id: 'readme', title: 'Readme'},
                {id: 'examples', title: 'Examples'},
                {id: 'doc', title: 'Documentation'},
                {id: 'downloads', title: 'Downloads'},
                {id: 'development', title: 'Development'}
            ],
            user: {
                item: {doc: '', examples: '', readme: ''},
                page: '',
                previousPage: 'about'
            }
        },
        db: Ox.localStorage('OxJS'),
        getCSS: function(element) {
            var css = {},
                home = app.url.get().page == '',
                center = Math.floor(window.innerWidth / 2),
                middle = Math.floor(window.innerHeight / 2);
            if (element == 'label') {
                css = home ? {
                    top: middle + 16 + 'px',
                    left: center - 128 + 'px',
                    width: '242px',
                    height: '16px',
                    fontSize: '12px',
                    opacity: 1,
                    overflow: 'visible'
                } : {
                    top: '35px',
                    left: '4px',
                    width: '40px',
                    height: '4px',
                    fontSize: '1px',
                    opacity: 0
                }
            } else if (element == 'loading') {
                css.top = middle + 52 + 'px'
            } else if (element == 'logo') {
                css = home || !app.state.loaded ? {
                    left: center - 128 + 'px',
                    top: middle - 128 + 'px',
                    width: '256px',
                    height: '128px',
                    borderRadius: '32px'
                } : {
                    top: '6px',
                    left: '6px',
                    width: '48px',
                    height: '24px',
                    borderRadius: '6px'
                };
            } else if (element == 'menu') {
                css = home ? {
                    top: middle + 56 + 'px',
                    left: Math.ceil(center - app.$ui.menu.width() / 2) + 'px'
                } : {
                    top: '6px',
                    left: Math.ceil(center - app.$ui.menu.width() / 2) + 'px'
                };
            } else if (element == 'screen') {
                css.opacity = home ? 1 : 0;
            } else if (element == 'switch') {
                css = home ? {
                    top: middle + 96 + 'px',
                    right: Math.floor(center - app.$ui.switch.width() / 2) + 'px'
                } : {
                    top: '6px',
                    right: '6px'
                };
            } else if (element == 'warning') {
                css = {
                    left: center - 128 + 'px',
                    top: middle + 16 + 'px',
                };
            }
            return css;
        },
        getSRC: function(element) {
            var src,
                home = app.url.get().page == '',
                theme = app.user.theme || 'classic';
            if (element == 'icon') {
                src = 'source/Ox.UI/themes/' + theme
                    + '/png/icon16.png';
            } else if (element == 'loading') {
                src = 'source/Ox.UI/themes/' + theme
                    + '/svg/symbolLoading.svg'
            } else if (element == 'logo') {
                src = 'source/Ox.UI/themes/' + theme
                    + '/png/logo128.png'                
            }
            return src;
        },
        html: {},
        init: function() {
            app.loadScreen(function() {
                app.loadData(function() {
                    Ox.load({UI: {theme: app.theme}}, app.load);
                });
            });
        },
        load: function(browserSupported) {
            var url = app.url.get();
            app.user = Ox.extend(app.data.user, app.db())
            app.user.page = url.page;
            if (url.item && url.page in app.user.item) {
                app.user.item[url.page] = url.item;
            }
            app.db(app.user);
            app.$ui.panel = app.ui.panel()
                .select(app.user.page)
                .appendTo(Ox.$body);
            // jqueryfy so that we can animate
            ['screen', 'logo', 'loading'].forEach(function(element) {
                app.$ui[element] = $('.' + element);
            });
            app.$ui.loading.animate({opacity: 0}, 500, function() {
                app.$ui.loading.remove();
            });
            if (!browserSupported) {
                app.$ui.warning = app.ui.warning()
                    .css(app.getCSS('warning'))
                    .appendTo(Ox.$body);
                app.$ui.logo
                    .css({cursor: 'pointer'})
                    .one({
                        click: function() {
                            app.$ui.warning.remove();
                            app.load(true);
                        }
                    });
            } else if (!url.page) {
                app.$ui.logo
                    .css({cursor: 'pointer'})
                    .on({
                        click: app.toggle
                    });
                ['label', 'menu', 'switch'].forEach(function(element) {
                    app.$ui[element] = app.ui[element]()
                        .css({opacity: 0})
                        .appendTo(Ox.$body);
                    app.$ui[element]
                        .css(app.getCSS(element))
                        .animate({opacity: 1}, 500);
                });
            } else {
                ['label', 'menu', 'switch'].forEach(function(element) {
                    app.$ui[element] = app.ui[element]().appendTo(Ox.$body);
                    app.$ui[element].css(app.getCSS(element)).hide();
                });
                app.$ui.screen.animate({opacity: 0}, 500, function() {
                    app.$ui.screen.hide();
                });
                app.$ui.logo.animate({opacity: 0}, 500, function() {
                    app.$ui.logo
                        .attr({src: app.getSRC('logo')})
                        .css(app.getCSS('logo'))
                        .animate({opacity: 1}, 500, function() {
                            app.$ui.logo
                                .css({cursor: 'pointer'})
                                .on({
                                    click: app.toggle
                                });
                        });
                    app.$ui.switch.css({opacity: 0}).show().animate({
                        opacity: 1
                    }, 500);
                });
            }
            Ox.$window.on({
                hashchange: app.urlchange
            });
            app.state.loaded = true;
        },
        loadData: function(callback) {
            Ox.getJSON('index.json?'+Ox.random(1000), function(data) {
                app.data = Ox.extend(app.data, data);
                app.data.pages.forEach(function(page) {
                    var id = page.id == 'doc' ? 'documentation' : page.id;
                    Ox.get('readme/html/_' + (id) + '.html', function(html) {
                        app.html[id] = html;
                        Ox.len(app.html) == app.data.pages.length && callback();
                    });
                })
            });
        },
        loadScreen: function(callback) {
            app.setTheme(app.user.theme || 'classic');            
            app.$ui.screen = app.ui.screen();
            app.$ui.loading = app.ui.loading();        
            app.$ui.logo = app.ui.logo()
                .one({
                    load: function() {
                        Ox.$('body')
                            .append(app.$ui.screen)
                            .append(app.$ui.logo)
                            .append(app.$ui.loading);
                        app.rotate();
                        callback();
                    }
                });
            Ox.$(window).on({
                resize: app.resize
            });
        },
        patchButtonGroup: function($buttonGroup) {
            $buttonGroup.find('.OxButton').css({
                height: '22px',
                paddingLeft: '8px',
                paddingRight: '8px',
                fontSize: '13px'
            });
            $buttonGroup.find('.OxButton:first-child').css({
                //paddingLeft: '9px',
                borderTopLeftRadius: '6px',
                borderBottomLeftRadius: '6px'
            });
            $buttonGroup.find('.OxButton:last-child').css({
                //paddingRight: '9px',
                borderTopRightRadius: '6px',
                borderBottomRightRadius: '6px'
            });
        },
        re: {
            code: [
                new RegExp(
                    '<span class="OxIdentifier">Ox</span>'
                    + '(<span class="OxOperator">\\.</span>'
                    + '<span class="OxIdentifier">UI</span>)?'
                    + '<span class="OxOperator">\\.</span>'
                    + '<span class="Ox\\w+">([\\$\\w]+)<\\/span>',
                    'g'
                ),
                function (str) {
                    return '<a href="#doc/' + Ox.stripTags(str)
                        + '" class="doclink">' + str + '</a>';
                }
            ],
            comment: [
                /\b(Ox\.[\w\$_]+)/g,
                '<a href="#doc/$1" class="OxMonospace doclink">$1</a>'
            ],
            version: [
                '{version}',
                function() {
                    return (
                        /:\/\/oxjs.org\//.test(window.location.href)
                            ? 'The latest version is'
                            : 'You\'re currently running version'
                    ) + ' <code>' + Ox.VERSION + '.</code>'
                }
            ]
        },
        resize: function() {
            [
                'logo', 'loading', 'label', 'menu', 'switch'
            ].forEach(function(element) {
                app.$ui[element] && app.$ui[element].css(app.getCSS(element));
            });
        },
        rotate: function() {
            var css, deg = 0,
                previousTime = +new Date(),
                interval = setInterval(function() {
                    var currentTime = +new Date(),
                        delta = (currentTime - previousTime) / 1000,
                        loadingIcon = document.getElementById('loadingIcon');
                    if (loadingIcon) {
                        previousTime = currentTime;
                        deg = Math.round((deg + delta * 360) % 360 / 30) * 30;
                        css = 'rotate(' + deg + 'deg)';
                        loadingIcon.style.MozTransform = css;
                        loadingIcon.style.MSTransform = css;
                        loadingIcon.style.OTransform = css;
                        loadingIcon.style.WebkitTransform = css;
                    } else {
                        clearInterval(interval);
                    }
                }, 83);
        },
        setTheme: function(theme) {
            app.user.theme = theme;
            app.db(app.user);
            (Ox.$('#icon') || Ox.$('<link>').attr({
                id: 'icon',
                rel: 'shortcut icon',
                type: 'image/png'
            }).appendTo(Ox.$('head'))).attr({
                href: app.getSRC('icon')
            });
            app.$ui.logo && app.$ui.logo
                .attr({src: app.getSRC('logo')})
                .css(app.getCSS('logo'));
            Ox.Theme
                ? Ox.Theme(theme)
                : Ox.$('body').addClass('OxTheme' + Ox.toTitleCase(theme)
            );
        },
        state: {
            animating: false,
            loaded: false
        },
        toggle: function() {
            !app.state.animating && app.url.set(
                app.url.get().page ? {
                        page: '',
                        item: ''
                    } : {
                        page: app.user.previousPage,
                        item: app.user.previousPage in app.user.item
                            ? app.user.item[app.user.previousPage] : ''
                    }
            );
        },
        ui: {
            doc: function() {
                return Ox.DocPanel({
                        element: $('<div>')
                            .addClass('Ox___Serif page')
                            .css({
                                margin: '32px',
                                width: window.innerWidth - 640 + 'px'
                            })
                            .html(app.html.documentation),
                        files: app.data.docItems ? void 0 : app.data.documentation,
                        getModule: function(item) {
                            var file = item.file.replace(/^dev\//, '');
                            return file.split('/')[0];
                        },
                        getSection: function(item) {
                            var file = item.file.replace(/^dev\//, '');
                            return item.section || file.split('/')[2].split('.')[0];
                        },
                        items: app.data.docItems || void 0,
                        path: 'dev/',
                        replace: [app.re.code],
                        selected: app.user.item.doc
                    })
                    .bindEvent({
                        select: function(data) {
                            app.user.item.doc = data.id;
                            app.db(app.user);
                            app.url.set();
                        }
                    })
                    .bindEventOnce({
                        load: function(data) {
                            app.data.docItems = data.items;
                        }
                    });
            },
            examples: function() {
                return Ox.ExamplePanel({
                        element: $('<div>')
                            .addClass('Ox___Serif page')
                            .css({
                                margin: '32px',
                                width: window.innerWidth - 640 + 'px'
                            })
                            .html(app.html.examples),
                        examples: app.data.examples,
                        keywords: /\b(Ox\.[\w]+)\b/g,
                        path: 'examples/',
                        replaceCode: [app.re.code],
                        replaceComment: [app.re.comment],
                        selected: app.user.item.examples
                    })
                    .bindEvent({
                        select: function(data) {
                            app.user.item.examples = data.id;
                            app.db(app.user);
                            app.url.set();
                        }
                    });
            },
            label: function() {
                return Ox.Label({
                        textAlign: 'center',
                        title: 'A JavaScript Library for Web Applications',
                        width: 256
                    })
                    .addClass('label animate')
                    .css({
                        paddingTop: '4px',
                        paddingBottom: '4px',
                        borderRadius: '6px'
                    })
                    .on({
                        click: app.toggle
                    });
            },
            loading: function() {
                return Ox.$('<img>')
                    .addClass('loading')
                    .attr({id: 'loadingIcon', src: app.getSRC('loading')})
                    .css(app.getCSS('loading'));
            },
            logo: function() {
                return Ox.$('<img>')
                    .addClass('logo animate')
                    .attr({src: app.getSRC('logo')})
                    .css(app.getCSS('logo'));
            },
            menu: function() {
                var $menu = Ox.ButtonGroup({
                        buttons: app.data.pages,
                        min: 0,
                        selectable: true,
                    })
                    .addClass('menu animate')
                    .bindEvent({
                        change: function(data) {
                            if (data.value) {
                                app.url.set({page: data.value});
                            }
                        }
                    })
                app.patchButtonGroup($menu);
                return $menu;
            },
            page: function(page, replace) {
                var $element = Ox.Container();
                $('<div>')
                    .addClass('Ox____Serif OxSelectable page')
                    .html(app.html[page].replace(app.re.version[0], app.re.version[1]))
                    .appendTo($element);
                return $element;
            },
            panel: function() {
                var $panel = Ox.TabPanel({
                            content: function(id) {
                                return app.$ui[id] = app.ui[id]
                                    ? app.ui[id]() : app.ui.page(id);
                            },
                            size: 36,
                            tabs: app.data.pages
                        })
                        .bindEvent({
                            change: function(data) {
                                if (app.state.loaded) {
                                    app.user.page = data.selected;
                                    app.db(app.user);
                                    app.url.set();
                                }
                            }
                        }),
                    $buttonGroup = $panel.find('.OxButtonGroup').css({
                        top: '6px'
                    });
                app.patchButtonGroup($buttonGroup);
                return $panel;
            },
            readme: function() {
                var $list = Ox.Container().css({overflowY: 'scroll'}),
                    $text = Ox.Container().addClass('OxSerif OxSelectable text'),
                    self = {},
                    that = Ox.SplitPanel({
                            elements: [
                                {element: $list, size: 256},
                                {element: $text}
                            ],
                            orientation: 'horizontal'
                        }, self)
                        .addClass('readme');
                Ox.sortBy(app.data.readme, '-date').forEach(function(item, i) {
                    var $item = $('<div>')
                            .addClass('item')
                            .attr({id: 'readme_' + item.id})
                            .css({
                                width: 224 - Ox.UI.SCROLLBAR_SIZE + 'px'
                            })
                            .on({
                                click: function(e) {
                                    if (!$(this).is('.selected')) {
                                        selectItem(item.id);
                                    } else if (e.metaKey) {
                                        selectItem();
                                    }
                                }
                            })
                            .appendTo($list);
                    $('<div>')
                        .addClass('OxSerif title')
                        .html(item.title)
                        .appendTo($item);
                    $('<div>')
                        .addClass('OxSerif OxLight date')
                        .html(Ox.formatDate(item.date, '%B %e, %Y', true))
                        .appendTo($item);
                });
                selectItem(app.user.item.readme);
                function selectItem(id) {
                    $('.readme .item.selected').removeClass('selected');
                    id && $('#readme_' + id).addClass('selected');                    
                    Ox.get('readme/html/' + (id || '_readme') + '.html', function(html) {
                        $text.empty()
                            .append(
                                id ? html
                                : $('<div>')
                                    .addClass('Ox___Serif page')
                                    .css({
                                        margin: '16px',
                                        width: window.innerWidth - 640 + 'px'
                                    })
                                    .html(html)
                            )
                            .find('.code').each(function() {
                                var $this = $(this);
                                $this.replaceWith(
                                    Ox.SyntaxHighlighter({
                                        source: $this.text()
                                    })
                                    .attr({id: $this.attr('id')})
                                );
                            });
                    });
                    app.user.item.readme = id;
                    app.db(app.user);
                    app.url.set();
                }
                self.setOption = function(key, value) {
                    if (key == 'selected') {
                        selectItem(value);
                    }
                }
                return that;
            },
            screen: function() {
                return Ox.$('<div>').addClass('screen animate');
            },
            switch: function() {
                var $switch = Ox.ButtonGroup({
                        buttons: [
                            {id: 'classic', title: 'Light'},
                            {id: 'modern', title: 'Dark'}
                        ],
                        selectable: true,
                        value: app.user.theme
                    })
                    .addClass('switch animate')
                    .bindEvent({
                        change: function(data) {
                            app.setTheme(data.value);
                        }
                    });
                app.patchButtonGroup($switch);
                return $switch;
            },
            warning: function() {
                return $('<div>')
                    .addClass('warning')
                    .html(
                        'Aw, snap! This website requires an up-to-date, HTML5-compliant web browser. '
                        + 'It should work fine in current versions of '
                        + '<a href="http://google.com/chrome/">Chrome</a>,'
                        + '<a href"http://mozilla.org/firefox/">Firefox</a> '
                        + 'and <a href="http://apple.com/safari/">Safari</a>, '
                        + 'or Internet Explorer with <a href="http://google.com/chromeframe/">Chrome Frame</a> installed. '
                        + 'To proceed at your own risk, click on the logo above.'
                    );
            }
        },
        url: {
            get: function() {
                var split = window.location.hash.slice(1).split('/');
                return {page: split[0], item: split[1] || ''};
            },
            set: function(data) {
                data = data || app.user;
                window.location.hash = data.page + (
                    data.item && data.item[data.page] ? '/' + data.item[data.page] : ''
                );
                return app;
            }
        },
        urlchange: function() {
            var url = app.url.get();
            app.user.previousPage = app.user.page;
            app.user.page = url.page;
            if (url.item && url.page in app.user.item) {
                app.user.item[url.page] = url.item;
            }
            app.db(app.user);
            if (app.user.page != app.user.previousPage) {
                app.$ui.panel.select(app.user.page);
            }
            if (url.item) {
                app.$ui[url.page].options({selected: url.item});
            }
            if (!app.user.page || !app.user.previousPage) {
                app.animate();
            }
        },
        user: {}
    };

    app.init();
    window.oxjs = app;

});