var Node = new Class({
    initialize: function(label, code, slug, tags, children, sortOrder) {
        this.label = label;
        this.code = code;
        this.slug = slug;
        this.sortOrder = sortOrder.toInt();
        this.tags = tags || "";
        this.parentNode = false;
        this.children = children || [];
    },
    setChildren: function(children) {
        this.children = children;
        for(var i=0; i<this.children.length; ++i) {
            this.children[i].parentNode = this;
        }
    },
    getChildren: function() {
        var nodes = this.children;
        return this._doSort(nodes);
    },
    getGrandchildren: function() {
        var nodes = this.children.map(function(node) {
            return node.getChildren();
        }).flatten().clean();
        return this._doSort(nodes);
    },
    _doSort: function(nodes) {
        var arr = $A(nodes);
        arr.sort(function(a,b) {
            if(a.sortOrder < b.sortOrder) return -1;
            if(a.sortOrder > b.sortOrder) return 1;
            if(a.sortOrder == b.sortOrder) return 0;
        });
        return arr;
    },
    getNode: function(code) {
        if(this.code == code) return this;
        if(!this.children.length) return null;
        var ret = null
        for(var i=0; i<this.children.length; ++i) {
            ret = (this.children[i]).getNode(code);
            if(ret != null) break;
        }
        return ret;
    },
    getAncestors: function() {
        var ancestors = [];
        var p = this.parentNode;
        while(p) {
            ancestors.push(p);
            p = p.parentNode;
        }
        return ancestors;
    },
    getHierarchy: function() {
        var a = this.getAncestors();
        return [this].concat(a);
    }
});

var Dialog = new Class({
    Implements: [Options, Events, Chain],
    
    options: {
        popupBg: false,
        closeable: false,
        zIndex: 1000,
        windowClass: false,
        clone: true,
        fauxPage: false
    },
    
    initialize: function(el, options) {
        this.setOptions(options);
        if(!Dialog.popupBg) {
            Dialog.popupBg = new Element('div', {
                id: 'dialog-overlay',
                styles: {display: 'none', zIndex: this.options.zIndex}
            });
            Dialog.popupBg.inject($(document.body), 'bottom');
        }
        if(this.options.clone) {
            this.element = $(el).clone();
            this.element.inject($(document.body), 'bottom');
        } else this.element = $(el);
        if(this.options.windowClass) {
            this.element.addClass(this.options.windowClass);
        }
        this.element.setStyles({
            'position': 'absolute',
            'z-index': this.options.zIndex + 2
        });
        this.element.getElements('.close-dialog').addEvent('click', function(ev) {
            ev.stop();
            this.hide();
        }.bind(this));
        this.hideTimer = false;
    },
    show: function() {
        $clear(this.hideTimer);
        if(this.options.fauxPage) {
            var pos = $('content-container').getCoordinates();
            this.element.setStyles({
                'position': 'absolute',
                'z-index': this.options.zIndex + 2,
                'top': pos.top+5,
                'left': pos.left+5,
                'height': pos.height-20,
                'width': pos.width-(Browser.Engine.trident ? 22 : 21)
            });
            this.element.addClass('faux-page');
            this.element.getElement('.body').setStyle('height', pos.height-80);
            this.element.setStyle('display', 'block');
            Dialog.popupBg.addClass('faux-page');
        } else {
            Dialog.popupBg.removeClass('faux-page');
            this.element.setStyle('display', 'block');
            this.resize();
        }
        
        Dialog.popupBg.setStyle('display', 'block');
        $(document.body).addClass('overlayed');
        return this;
    },
    expose: function(delay) {
        this.show();
        this.hideTimer = this.hide.delay(delay, this);
    },
    resize: function() {    
        var size = $(document).getSize(), scroll = $(document).getScroll(), ssize = $(document).getScrollSize();
        Dialog.popupBg.setStyles({
            width: ssize.x + 'px',
            height: ssize.y + 'px'
        });    
        if(this.options.fauxPage) {
            Dialog.popupBg.addClass('faux-page');
        } else {
            var top = (size.y - this.element.offsetHeight) / 2;
            this.element.setStyles({
                left: (scroll.x + (size.x - this.element.offsetWidth) / 2).toInt() + 'px',
                top: (scroll.y + top < 0 ? 10: scroll.y + top).toInt() + 'px'
            });
        }
        return this;
    },
    hide: function() {
        this.element.setStyle('display', 'none');
        Dialog.popupBg.setStyle('display', 'none');
        Dialog.popupBg.removeClass('faux-page');
        $(document.body).removeClass('overlayed');
        return this;
    }
});

Element.Properties.options = {
    set: function(opts) {
        this.options.length = 0;
        for(var i=0; i<opts.length; i++) {
            this.options[i] = opts[i];
        }
    }
};

var LocationsDialog = new Class({
    Extends: Dialog,
    options: {
        closeable: true,
        onlyCities: false
    },
    worldwide: false,
    initialize: function(el, tree, options) {
        this.parent(el, options);
        var worldwide = $(tree).getElement('ul li');
        this.body = this.element.getElement('.body');
        this.locationTmpl = this.body.getElement('.locationTmpl')
        if(!LocationsDialog.worldwide) LocationsDialog.worldwide = this.parseNode(worldwide);
        this.worldwide = LocationsDialog.worldwide;
        this.currentPlace = false;
        this.reset();
        this.attach();
    },
    parseNode: function(el) {
        if(!el) return false;
        var a = el.getElement('a');
        var s = el.getElement('ul');
//         console.log('parsing Node', a);
        if(s) children = this.parseNodes(s.getChildren('li'));
        else children = [];
        var n = new Node(a.get('text'), a.get('dyncode'), a.get('dynslug'), a.get('dyntags'), [], a.get('dynsort'));
        n.setChildren(children);
        return n;
    },
    parseNodes: function(els) {
        var self = this;
        return els.map(function(el) {
            return self.parseNode(el);
        });
    },
    attach: function() {
        this.body.getElements('.region-box select').addEvent('change', this.locationChanged.bindWithEvent(this));
        this.body.addEvent('click', function(ev) {
            var location = null;
            if( $(ev.target).match('a.location') ) {
                ev.stop();
                location = $(ev.target);
            } else if($(ev.target).match('span.place') ) {
                ev.stop();
                location = $(ev.target).getParent('a');
            } else {
                return;
            }
            var code = location.get('href');
            var node = this.worldwide.getNode(code);
            if(node) this.fireEvent('change', [node.code, node.label, node.slug, node]);
        }.bind(this));
    },
    reset: function() {
        this.body.getElements('.region-box').setStyle('display', 'none');
        var cbox = this.body.getElement('.country');
        this.fillRegionNode(cbox, this.worldwide, false);
        cbox.setStyle('display', 'block');
        this.resize();
        return this;
    },
    setPlace: function(place) {
        this.currentPlace = this.worldwide.getNode(place);
        if(!this.currentPlace) this.currentPlace = this.worldwide;
        if(this.currentPlace.slug == 'worldwide') {
            this.getBox('country').getElement('.location').addClass('current');
            return;
        } else {
            this.getBox('country').getElement('.location').removeClass('current');
        }
        var ancestors = this.currentPlace.getHierarchy();
        ancestors.pop(); //discard worldwide
        var country = ancestors.pop();
//         console.log('countr', country);
        var select = this.getBox('country').getElement('select');
        this.setIndex(country, select);
        this.locationChanged({target: select});
        if(!ancestors.length) return;
        var nextNode = false;
        var nextLevel = false;
        if(country.slug == 'worldwide-usa') {
            nextNode = ancestors.pop();
            nextLevel = 'region';
            var select = this.getBox(nextLevel).getElement('select');
            this.setIndex(nextNode, select);
            this.locationChanged({target: select});
        } else {
            ancestors.pop(); //discard region
        }
        if(!ancestors.length) return;
        nextNode = ancestors.pop();
        nextLevel = 'province';
        var select = this.getBox(nextLevel).getElement('select');
        this.setIndex(nextNode, select);
        this.locationChanged({target: select});
        return this;
    },
    setIndex: function(node, select) {
        for(var x=0; x<select.options.length; x++) {
            if( select.options[x].value == node.code ) {
                select.selectedIndex = x;
                return true;
            }
        }
        return false;
    },
    fillRegionNode: function(box, node, fillGrandchildren) {
        var select = $(box).getElement('select');
        var nodes = null;
        if(fillGrandchildren) {
            nodes = node.getGrandchildren();
        } else {
            nodes = node.getChildren();
        }
        var options = nodes.map(function(n) {
            var o = new Option();
            o.value = n.code;
            o.text = n.label;
            return o;
        });
        var def = new Option();
        def.value = '-1';
        def.text = 'Choose...'
        options.splice(0,0,def);
        select.set('options', options);
        $(box).getElement('.location').setStyle('display', this.options.onlyCities ? 'none': '');
        $(box).getElements('.or').setStyle('display', this.options.onlyCities ? 'none': '');
        $(box).getElement('.place').set('text', node.label);
        $(box).getElement('.location').set('href', node.code);
        if(node == this.currentPlace) $(box).getElement('.location').addClass('current');
        else $(box).getElement('.location').removeClass('current');
        if(node.tags.contains('new')) $(box).getElement('.location').addClass('new');
        else $(box).getElement('.location').removeClass('new');
    },
    fillDetailNode: function(box, node) {
        var list = $(box).getElement('ul.cities');
        list.empty();
        $(box).getElement('.location').setStyle('display', this.options.onlyCities ? 'none': '');
        $(box).getElements('.or').setStyle('display', this.options.onlyCities ? 'none': '');
        $(box).getElement('.place').set('text', node.label);
        $(box).getElement('.location').set('href', node.code);
        if(node == this.currentPlace) $(box).getElement('.location').addClass('current');
        else $(box).getElement('.location').removeClass('current');
        if(node.tags.contains('new')) $(box).getElement('.location').addClass('new');
        else $(box).getElement('.location').removeClass('new');
        var nodes = node.getGrandchildren();
        for(var i=0; i<nodes.length; i++) {
            var n = nodes[i];
            var children = this.fillNodeList(n);
            if(children.length) children.each(list.adopt.bind(list));
        }
    },
    fillNodeList: function(node) {
        var copy = false;
        if(this.options.onlyCities & node.tags.contains('city') || !this.options.onlyCities) {
            copy = this.locationTmpl.clone();
            copy.set('html', node.label).set('href', node.code);
            if(node == this.currentPlace) copy.addClass('current');
            else copy.removeClass('current');
            if(node.tags.contains('new')) copy.addClass('new');
            else copy.removeClass('new');
            var e = new Element('li');
            copy.inject(e);
        }
        var list = false;
        if(node.children.length){
            var children = node.children.map(this.fillNodeList.bind(this));
            children = children.filter($chk);
            if(children && children.length) {
                if(copy) {
                    list = new Element('ul');
                    children.flatten().each(list.adopt.bind(list));
                } else {
                    list = children;
                }
            }
        }
        if(list && copy) {
            list.inject(e);
            return [e];
        } else if(!list && copy) {
            return [e];
        } else if(list) {
            return list;
        } else return false;
    },
    getBox: function(type) {
        return this.body.getElement('.'+type+'.region-box');
    },
    locationChanged: function(ev) {
        var select = $(ev.target);
        var locType = select.getParent('.region-box').get('dyntype');
        if(locType == 'country') {
            if(select.value == '-1') {
                this.body.getElements('.region.region-box, .province.region-box, .city.region-box').setStyle('display', 'none');
            } else {
                var n = this.worldwide.getNode(select.value);
                if(n.slug == 'worldwide-usa') {
                    this.body.getElements('.province.region-box, .city.region-box').setStyle('display', 'none');
                    var box = this.getBox('region');
                    this.fillRegionNode(box, n);
                    box.setStyle('display', 'block');
                } else { 
                    this.body.getElements('.region.region-box, .city.region-box').setStyle('display', 'none');
                    var box = this.getBox('province');
                    this.fillRegionNode(box, n, true);
                    box.setStyle('display', 'block');
                }
                
            }
        } else if(locType == 'region') {
            var n = this.worldwide.getNode(select.value);
            if(n) {
                this.body.getElements('.city.region-box').setStyle('display', 'none');
                var box = this.getBox('province');
                this.fillRegionNode(box, n);
                box.setStyle('display', 'block');
            } else {
                this.body.getElements('.province.region-box, .city.region-box').setStyle('display', 'none');
            }
        } else if(locType == 'province') {
            var n = this.worldwide.getNode(select.value);
            if(n) {
                var box = this.getBox('city');
                this.fillDetailNode(box, n);
                box.setStyle('display', 'block');
            } else {
                this.body.getElements('.city.region-box').setStyle('display', 'none');
            }
        }
        this.resize();
    },
    
    getLocationLabelFor: function(code) {
        return this.worldwide.getNode(code).label;
    }
});

window.addEvent('domready', function() {
//     console.log('LocationsDialog');
    var ld = new LocationsDialog($$('.locations-dialog')[0], 'locations-tree', { fauxPage: true });
//     console.log('LocationsDialog 2');
    LocationsDialog.instance = ld;
    if($(document.body).hasClass('search-center-rail')) {
        $$('#main-change-city').addEvent('click', function(ev) {
            ev.stop();
            var ldi = LocationsDialog.instance;
            ldi.reset();
            if($('search-city').value) {
                ldi.setPlace($('search-city').value);
            }
            ldi.show();
            function f(code, label, slug) {
                ldi.removeEvents('change');
                ldi.hide();
                $('main-city-display').getElement('.city-name').set('text', label);
                Cookie.write('PREF_LOCATION', label, {path: '/', duration:300});
                Cookie.write('PREF_LOCATION_CODE', code, {path: '/', duration:300});
                $('search-city').value = code;
                $('search-form').submit();
            }
            ldi.removeEvents('change').addEvent('change', f);
        });
    } else {
        $$('#main-change-city, #buy a').addEvent('click', function(ev) {
//             console.log('clicked on main chinge');
            ev.stop();
            var ldi = LocationsDialog.instance;
            ldi.reset();
            if($('search-city-form').getElement('input').value) {
                ldi.setPlace($('search-city-form').getElement('input').value);
            }
            ldi.show();
            function f(code, label, slug) {
                ldi.removeEvents('change');
                ldi.hide();
                $('main-city-display').getElement('.city-name').set('text', label);
                Cookie.write('PREF_LOCATION', label, {'path': '/', 'duration':300});
                Cookie.write('PREF_LOCATION_CODE', code, {'path': '/', 'duration':300});
                $('search-city-form').getElement('input').value = code;
                $('search-city-form').submit();
            }
            ldi.removeEvents('change').addEvent('change', f);
        });
    }
    
    $$('a.button.auto').addEvent('click', function(ev) {
        ev.stop();
        var x  = $(this).getParent('form');
        x.submit();
    });
    
});