/**
 * Super first search view and controller
 *
 */

(function () {

    TRAVEL.namespace('TRAVEL.SuperFirst');

    // roor -> #head-map
    TRAVEL.SuperFirst.Search = function (root) {
        var self = TRAVEL.Observable2(this);
        var searchPanel = null;

        self.create = function (model) {
            searchPanel = new TRAVEL.SuperFirst.SearchPanel(root);
            searchPanel.create(model);
            searchPanel.attachObserver('modelChanged', function (data) {
                self.notify('modelChanged', data);
            });
        };

        self.updateResults = function (count, link) {
            if (searchPanel) {
                searchPanel.updateResults(count, link);
            }
        };
    };


    /**
     *
     * @event   typeChanged       {index, value}
     * @event   categoryChanged   {index, value}
     * @event   queryChanged      {value}
     * @event   modelChanged      {Object}        Delayed event for search request
     */
    TRAVEL.SuperFirst.SearchPanel = function (root) {
        var self = TRAVEL.Observable2(this);
        var gadget;
        var timer = null;

        var renderView = function (model) {
            var obj = [], i;

            obj.push('<div class="search-gadget">');

            obj.push('<div class="search-module search-result">',
                        '<div class="search-module-body"><div class="search-module-wrapper">',
                            '<h1 unselectable="on" class="unselectable"><span>0</span> träffar</h1>',
                            '<div class="list-button button"><span><a href="', baseUrl, '">Visa som lista</a></span></div>',
                            '<div class="map-button button"><span><a href="', baseUrl, '">Visa på karta</a></span></div>',
                        '</div></div>',
                        '<div class="search-module-cap"></div>',
                    '</div>');

            obj.push(
                '<div class="search-module search-type">',
                    '<div class="search-module-body"><div class="search-module-wrapper">',
                        '<h2>Sök</h2>',
                        '<ul class="unselectable">');
            for (i = 0; i < model.tobs.length; i++) {
                obj.push('<li unselectable="on" class="tobs', (i === model.tobs.length - 1 ? ' last' : ''),
                        '"><span>', model.tobs[i].name, '</span>',
                        '<em>&raquo;</em>',
                        '</li>');
            }
            obj.push(   '</ul>',
                        '<div class="reset">Rensa</div>',
                    '</div></div>',
                    '<div class="search-module-cap"></div>',
                '</div>',
                '<div class="search-module search-keyword">',
                    '<div class="search-module-body"><div class="search-module-wrapper">',
                        '<h2>Filtrera</h2>',
                        '<ul class="unselectable">');
/*
            for (i = 0; i < model.categories.length; i++) {
                obj.push('<li unselectable="on" class="keywords">',
                        '<span>', model.categories[i].name, '</span>',
                        '<em>&raquo;</em>',
                        '</li>');
            }
*/
            obj.push(   '<li class="regions last">',
                    '<span>Regioner</span><em>&raquo;</em>',
                '</li>');
            obj.push(   '</ul>',
                        '<div class="text hidden"><input type="text" value="" /></div>',
                        '<div class="reset">Rensa</div>',
                    '</div></div>',
                    '<div class="search-module-cap"></div>',
                '</div>');

            obj.push('</div>');

            $('div.search-gadget', root).remove();
            $(root).append(obj.join(''));
            // get gadget's root
            gadget = $('div.search-gadget', root);
            // fix layout for 24-bit png in IE
            $('div.search-module-wrapper', gadget).each(function () {
                var wEle = $(this);
                var pEle = $(this.parentNode);
                pEle.height(wEle.outerHeight());
                pEle.parent().append(wEle);
            });
        };

        var bindController = function (model) {

            var typeDiv = $('div.search-type', gadget);
            var catDiv = $('div.search-keyword', gadget);

            var submenu = new TRAVEL.SuperFirst.SubMenu();
            submenu.attachObserver('typeChanged', function () {
                self.notify('typeChanged');
            });
            submenu.attachObserver('regionChanged', function () {
                self.notify('regionChanged');
            });
            submenu.attachObserver('categoryChanged', function () {
                self.notify('categoryChanged');
            });

            typeDiv.each(function () {
                var div = $(this);
                var eles = $('li', div);
                $(this).click(function (e) {
                    var target = $(e.target), index;
                    do {
                        if (target.is('li')) {
                            index = eles.index(target);
                            if (index >= 0) {
                                submenu.show(target, model.tobs[index].subtobs, 'typeChanged');
                                e.stopPropagation();
                            }
                            break;
                        } else {
                            target = target.parent();
                        }
                    } while (target.length > 0 && div.get(0) !== target.get(0));
                });

                $('div.reset', this).click(function () {
                    var i, j, tob;

                    submenu.hide();

                    for (i = 0; i < model.tobs.length; i++) {
                        tob = model.tobs[i];
                        for (j = 0; j < tob.subtobs.length; j++) {
                            tob.subtobs[j].selected = false;
                        }
                    }
                    self.notify('typeChanged');
                });
            });

            catDiv.each(function () {
                var div = $(this);
                var eles = $('li', this);
                $(this).click(function (e) {
                    var target = $(e.target), index;
                    do {
                        if (target.is('li')) {
                            index = eles.index(target);
                            if (index === eles.length - 1) {
                                // regions
                                submenu.show(target, model.regions, 'regionChanged');
                                e.stopPropagation();
                            } else if (index >= 0) {
                                // keywords
                                submenu.show(target, model.categories[index].keywords, 'categoryChanged');
                                e.stopPropagation();
                            }
                            break;
                        } else {
                            target = target.parent();
                        }
                    } while (target.length > 0 && div.get(0) !== target.get(0));
                });

                $('div.reset', this).click(function () {
                    var i, j, category;

                    submenu.hide();

                    for (i = 0; i < model.categories.length; i++) {
                        category = model.categories[i];
                        for (j = 0; j < category.keywords.length; j++) {
                            category.keywords[j].selected = false;
                        }
                    }
                    self.notify('categoryChanged');

                    for (i = 0; i < model.regions.length; i++) {
                        model.regions[i].selected = false;
                    }
                    self.notify('regionChanged');

                    model.query = '';
                    $('div.text input', catDiv).val('');
                    self.notify('queryChanged');
                });
            });

            // query field
            $('div.text input', catDiv).keyup(function () {
                model.query = $(this).val();
                self.notify('queryChanged');
            });

        };

        var updateModel = function (model) {
            if (timer) {
                clearTimeout(timer);
            }
            (function (data) {
                timer = setTimeout(function () {
                    self.notify('modelChanged', data);
                    timer = null;
                }, 1000);
            })(model);
        };


        self.create = function (model) {
            renderView(model);
            bindController(model);

            self.attachObserver('queryChanged', function () {
                    updateModel(model);
                })
                .attachObserver('typeChanged', function () {
                    updateModel(model);
                })
                .attachObserver('categoryChanged', function () {
                    updateModel(model);
                })
                .attachObserver('regionChanged', function () {
                    updateModel(model);
                });
        };

        self.getGadget = function () {
            return gadget;
        };

        self.updateResults = function (count, link) {
            var ele = $('div.search-result h1', gadget);
            count = parseInt(count);
            if (!isNaN(count)) {
                $('span', ele).html('' + count);
            }

            if (link) {
                $('div.list-button a', gadget).attr('href', link);
                $('div.map-button a', gadget).attr('href', link.replace('-search', '-search-map'));
            }
        };

    };


    TRAVEL.SuperFirst.SubMenu = function () {

        var self = TRAVEL.Observable2(this);

        var targetItem;

        var MAX_ITEMS = 13;
        var SCROLL_SENS = 20;
        var DELAY_FIRST = 1000;
        var DELAY_OTHER = 200;

        function makeScrollable() {

            function scrollDown (panel) {

                $(panel).each(function () {

                    $('#search-submenu div.scroll').removeClass('disabled');

                    var top = parseInt($(this).css('top'));
                    top = isNaN(top) ? 0 : top - SCROLL_SENS;
                    if (top < heightMax - heightTotal) {
                        top = heightMax - heightTotal;
                        $('#search-submenu div.scroll-down').addClass('disabled');
                    }

                    $(this).css('top', top + 'px');
                })

            }

            function scrollUp (panel) {
                $(panel).each(function () {

                    $('#search-submenu div.scroll').removeClass('disabled');

                    var top = parseInt($(this).css('top'));
                    top = isNaN(top) ? 0 : top + SCROLL_SENS;
                    if (top > 0) {
                        top = 0;
                        $('#search-submenu div.scroll-up').addClass('disabled');
                    }

                    $(this).css('top', top + 'px');
                })
            }

            var heightMax = 5;
            var heightTotal;
            var container = $('#search-submenu div.scroll-container');
            var ulEle = $('ul', container);
            var liEles = $('li', container);

            liEles.slice(-MAX_ITEMS).each(function () {
                heightMax += $(this).outerHeight(true);
            });

            container.height(heightMax);
            heightTotal = ulEle.outerHeight(true);

            ulEle.css('position', 'absolute');

            $('#search-submenu div.scroll-up').mousedown(function () {
                scrollUp(ulEle);
            });
            $('#search-submenu div.scroll-down').mousedown(function () {
                scrollDown(ulEle);
            });

            container.mousewheel(function(event, delta) {
                if (delta > 0) {
                    scrollUp(ulEle);
                } else {
                    scrollDown(ulEle);
                }
                return false; // prevent default
            });

        }


        function fixPosition() {
            var layer = $('#search-submenu div.search-submenu-layer');
            var container = $('#head-map');
            if (container.length === 0 || container.outerHeight() <= 0) {
                container = $('body').eq(0);
            }

            var marginBottom = container.offset().top + container.outerHeight() - 32;
            var currentBottom = layer.offset().top + layer.outerHeight();

            if (marginBottom < currentBottom) {
                // gonna fix submenu position
                layer.css('top', marginBottom - currentBottom);
            }
        }

        self.isVisible = function () {
            return $('#search-submenu').length > 0;
        };

        self.hide = function () {
            $('#search-submenu').remove();
            targetItem = null;
        };

        self.show = function (targetEle, model, eventType) {

            var ele = $(targetEle);
            var pEle = $(targetEle).parents('div.search-module-wrapper').eq(0);

            if (targetItem && targetEle.get(0) === targetItem.get(0)) {
                self.hide();
                return;
            }

            self.hide();

            // store item
            targetItem = targetEle;

            var obj = [], i;

            obj.push('<div id="search-submenu">',
                    '<div class="search-submenu-layer">',
                        '<div class="search-submenu-body">',
                            '<div class="search-submenu-wrapper">',
                                '<div class="scroll scroll-up unselectable disabled">',
                                    '<span unselectable="on">&#9650;</span>',
                                '</div>',
                                '<div class="scroll-container">',
                                    '<ul class="unselectable">');
            for (i = 0; i < model.length; i++) {
                obj.push('<li unselectable="on" class="',
                            (model[i].selected ? 'add' : ''),
                            (i === model.length - 1 ? ' last' : ''),
                        '"><span>', model[i].name, '</span></li>');
            }
            obj.push(               '</ul>',
                                '</div>',
                                '<div class="scroll scroll-down unselectable">',
                                    '<span unselectable="on">&#9660;</span>',
                                '</div>',
                            '</div>',
                        '</div>',
                        '<div class="search-submenu-cap"></div>',
                    '</div>',
                    '<div class="search-submenu-knob"></div>',
                '</div>');

            pEle.before(obj.join(''));

            if (model.length > MAX_ITEMS) {
                makeScrollable();
            } else {
                $('#search-submenu div.scroll').addClass('hidden');
            }

            $('#search-submenu').css('top', -6);
            $('#search-submenu div.search-submenu-knob').css('top', ele.position().top);

            $('#search-submenu div.search-submenu-wrapper').each(function () {
                var wEle = $(this);
                var pEle = $(this.parentNode);
                pEle.height(wEle.outerHeight());
                pEle.parent().append(wEle);

                var eles = $('li', this);
                wEle.click(function (e) {
                    var target = $(e.target), index;
                    do {
                        if (target.is('li')) {
                            index = eles.index(target);
                            $(target).toggleClass('add');
                            model[index].selected = $(target).hasClass('add');
                            self.notify(eventType, {
                                'index': index,
                                'value': model[index].selected
                            });
                            break;
                        } else {
                            target = target.parent();
                        }
                    } while (target.length > 0 && wEle.get(0) !== target.get(0));
                });
            });

            $('body').click(function (e) {
                var inSubMenu = $(e.target).parents().andSelf().filter('#search-submenu').length > 0;
                if (!inSubMenu) {
                    self.hide();
                }
            });

            fixPosition();
        };
    };

})();
