var SearchFormClass = {
    // Main form object
    form: null,

    // Autocomplete for town input
    autocomplete: null,

    // Hash for future actions
    currentHash: null,

    // Current object settings
    settings: {
        flashMap : {
            // Selector for getting flash map
            containerId: 'home-map-container'
        },

        autocomplete: {
            serviceUrl: '/geo/city-suggest',
            noCache: true,
            onSelect : function(value, data){
                return SearchFormClass.changeTown(value, data);
            },
            width: 125
        },

        emptyElement: '--',

        defaultOption: function(){
            return '<option value="'
                    + SearchFormClass.settings.emptyElement
                    + '">'
                    + Lang._('Select')
                    + '</option>';
        },

        // Administrative level for geo dropboxes
        levels: {
            url: '/geo/{level}',
            list: ['country', 'region', 'province', 'locality'],
            callback: {
                country: function(data) {
                    return SearchFormClass.updateFlashMapCountry(data.id);
                },

                region: function(data) {
                    return SearchFormClass.updateFlashMapRegion();
                }
            },
            pre: {
                country: function(data) {
                    console.log(data);
                    if (data.current !== SearchFormClass.currentFlash.country) {
                        FlashMap._noFlashUpdate = false;
                    }

                    SearchFormClass.currentFlash.country = data.current;
                },

                region: function(data) {
                    console.log(data);
                    if (data.current !== SearchFormClass.currentFlash.region) {
                        FlashMap._noFlashUpdate = false;
                    }

                    SearchFormClass.currentFlash.region = data.current;
                }
            }
        }
    },

    currentFlash: {
        region: null,
        country: 109
    },

    // Flag for using Gmap Geo object
    isGeo: false,

    changeLevel: function(level, id, nextLevelCurrentItem, preProcessing) {
        var levelIndex = $.inArray(level, this.settings.levels.list);
        if (-1 === levelIndex) {
            // Non existen level is given for processing
            return false;
        }

        var id = id || $('#' + level).val() || this.settings.emptyElement;
        var nextLevelCurrentItem = nextLevelCurrentItem || false;

        // Find levels for future processing
        var nextLevelList = this.settings.levels.list.slice(levelIndex+1,
                                                             this.settings.levels.list.length);

        // For each next level remove all options except the first
        $.each(nextLevelList, function(index,curLevel){
            $('#' + curLevel + ' option[value!="--"][value!="0"]').remove();
        });

        // Call callback function for current level, if defined
        if (!preProcessing && 'function' == typeof(pre = SearchFormClass.settings.levels.pre[level])) {
            pre({current: id});
        }

        if (id != this.settings.emptyElement) {
            this.lock();

            return this.loadLevelData(level, id,function(data){
                SearchFormClass.unlock();
                SearchFormClass.initAutocomplete();

                if (levelIndex < SearchFormClass.settings.levels.list.length-1) {
                    // Add areas on the form
                    SearchFormClass.addLevelOptions(SearchFormClass.settings.levels.list[levelIndex+1],
                                                    data[level].items, nextLevelCurrentItem);

                    // For each element of up to next level disable and update (already erased)
                    if ((lenght = nextLevelList.length) > 0) {
                        nextLevelList = nextLevelList.slice(1,lenght);
                        SearchFormClass.disable(nextLevelList);
                        SearchFormClass.selectboxUpdate(nextLevelList);
                    }
                }

                // Call callback function for current level, if defined
                if ('function' == typeof(callback = SearchFormClass.settings.levels.callback[level])) {
                    callback(data);
                }
            });
        }

        this.disable(nextLevelList);
        this.selectboxUpdate(nextLevelList);
        // this.initAutocomplete();
        return true;
    },

    disable: function(elements) {
        $.each(elements, function(){
            $('#' + this)
                .attr('disabled','disabled')
                .parent('div').addClass('disabled')
        });
    },

    updateFlashMapCountry: function(country) {
        country = country || $('#country').val();

        if (!FlashMap._noFlashUpdate) {
            FlashMap.showCountry(country);
            FlashMap._noFlashUpdate = false;
        }
    },

    updateFlashMapRegion: function(region) {
        region = region || $('#region').val();

        if (!FlashMap._noFlashUpdate) {
            FlashMap.showRegion(region);
            FlashMap._noFlashUpdate = false;
        }
    },

    addLevelOptions: function (level, options, current) {
        // Add new options to the given dropbox
        levelDropbox = $('#' + level);

        levelDropbox.find('option').remove();
        levelDropbox.append(SearchFormClass.settings.defaultOption.call());

        needNextLevelUpdate = false;
        $.each(options, function(){
            select = $('<option value="'+ this.id +'" alt="' + this.alt + '">'+ this.name +'</option>');
            // If we find current item - we need to select this item
            // and than send signal to system for updating town field
            if (current && (current==this.id)) {
                // We don't need to proccess this IF block in future
                current = false;
                needNextLevelUpdate = true;
                select.attr('selected', 'selected');
            }

            levelDropbox.append(select);
        });

        // Work around bug with Safari empty default option for list
        if (0 == levelDropbox.find('option:selected').length) {
            levelDropbox.find('option').eq(0).attr('selected', 'selected');
        }

        // Work around SelectBox plugin
        levelDropbox.removeAttr('disabled').parent('div').removeClass('disabled');
        SearchFormClass.selectboxUpdate(level);
    },

    // Called when user write new value in town field (or check from suggested list)
    changeTown: function(value, data) {
        // Call callback function for current level, if defined
        if ('function' == typeof(callback = SearchFormClass.settings.levels.callback.town)) {
            callback(data);
        }

        place = {city: value};
        $.each(SearchFormClass.settings.levels.list, function(index, level){
            place[level] = data[level];
        });

        return SearchFormClass.processPlace(place);
    },

    // Change current form place to given
    // Use place object in this format: city, all other levels
    processPlace: function(place, startFrom) {
        var startFrom = startFrom || null;

        // It means, that we call this function for the first time
        if(null === startFrom) {
            // Set town
            $('#town').val(place.city);

            $.each(SearchFormClass.settings.levels.list, function(index, level){
                if (null !== startFrom) {
                    return false;
                }

                // Firtst non-eqivalent
                if (place[level] != $('#' + level).val()) {
                    return (startFrom=index);
                }
            });
        }

        // Check if there some new level for processing
        if (startFrom == SearchFormClass.settings.levels.list.length) {
            return true;
        }

        return SearchFormClass.processPlaceByLevel(place, startFrom);
    },

    // For each level:
    // - If given ID exists in list, just check it
    // - Else load for this level necessary data
    // - Give as callback function for next step
    processPlaceByLevel: function(place, levelIndex) {
        if (levelIndex >= SearchFormClass.settings.levels.list.length) {
            return true;
        }

        var level      = SearchFormClass.settings.levels.list[levelIndex];
        var levelDOM   = $('#' + level);
        var place      = place;
        var levelIndex = ++levelIndex;

        // Check if ID already exists in the list of level options
        if (1 == levelDOM.find('option[value="' + place[level] + '"]').length && (levelDOM.val() != place[level])) {
            levelDOM.val(place[level]);

            // Work around SelectBox plugin
            SearchFormClass.selectboxUpdate(level);
        }

        // Don't need to lock for country level
        // Workaround bug #CH-124
        if(levelIndex != 1) {
            SearchFormClass.lock();
        }

        // We have to load new list of items for current level,
        // cause last filling were empty for this
        SearchFormClass.loadLevelData(level, place[level], function(data){
            SearchFormClass.unlock();
            if (levelIndex >= SearchFormClass.settings.levels.list.length) {
                return true;
            }

            // Change server-side answer for more consistent processing
            // (don't return next-level items with index of next level name)
            next = SearchFormClass.settings.levels.list[levelIndex];
            SearchFormClass.addLevelOptions(next, data[level].items, place[next]);
            return SearchFormClass.processPlaceByLevel(place, levelIndex);
        });

    },

    // Load information about given level and items from next down level
    loadLevelData: function(level, id, callback) {
        // Check if this level exists in level list
        if (-1 === $.inArray(level, SearchFormClass.settings.levels.list)) {
            return false;
        }

        if (SearchFormClass.isGeo) {Geo.showIndicator();}

        // Parend function realization
        params = {};
        params[level] = id;
        $.getJSON(
            SearchFormClass.settings.levels.url.replace('{level}',level),
            params,
            function(data,status){
                if (SearchFormClass.isGeo) {Geo.hideIndicator();}
                if( !data || !data.ok ) {
                    return false;
                }
                return callback(data);
            }
        );

        return true;
    },

    toggleLabel: function(condition, label) {
        if (condition) {
            $(label).css('display', 'block');
        } else {
            $(label).hide();
        }

        return false;
    },

    lock: function() {
        this.form.find('input[type=submit]').attr('disabled', 'disabled');
    },

    unlock: function() {
        this.form.find('input[type=submit]').attr('disabled',null);
    },

    selectboxUpdate: function(ids, options) {
        options = options || {};

        // Create new array if necessary
        if (typeof ids == 'string') {
            ids = [ids];
        }

        // Work with each element separatly
        $.each(ids, function(index, id){
            $('#' + id + '_wrapper').remove();
            $('#' + id).selectbox(options);
        });

        SearchFormClass.initAutocomplete()
    },

    setDefaultValue: function(input) {
        input = $(input);
        title = input.attr('title');

        if (input.val()=='' && title!='') {
            input.val(title);
        }
    },

    dropDefaultValue: function(input) {
        input = $(input);
        title = input.attr('title');

        if (input.val()==title) {
            input.val('');
        }
    },

    initAutocomplete: function() {
        params   = {limit: 25};
        $.each(SearchFormClass.settings.levels.list, function(index,level){
            value = $('#' + level).val();
            if (SearchFormClass.settings.emptyElement != value) {
                params[level] = value;
            }
        });

        // Change params of autocompleter
        this.autocomplete.setOptions({params: params});
    },

    // Select "For sale" and bind to change
    // it show on don`t show "Per month" label
    // This block diffs from extend form variant
    initGoalCheckbox: function() {
        goal = SearchFormClass.form.find('input[name=goal]');

        if (!goal.eq(0).attr('checked') && !goal.eq(1).attr('checked')) {goal.eq(0).click();}
        if (goal.eq(1).attr('checked')) {
            $('label.per-month').css('display','block');
        }

        goal.unbind().bind('change',{}, function(){
            return SearchFormClass.toggleLabel($(this).val()=='rent','label.per-month');
        });
    },

    predefineCounty: function() {
        this.changeLevel('country', 109);
    },

    init: function() {
        // Set checkbox with goal (rent, sale) to right form
        SearchFormClass.initGoalCheckbox();

        $('#property_types li.all > input[type="checkbox"]').unbind()
            .bind('change',{},function(){checkAllPrettyCheckboxes(this,$('#property_types'));});
        $('#property_features li.all > input[type="checkbox"]').unbind()
            .bind('change',{},function(){checkAllPrettyCheckboxes(this,$('#property_features'));});

        // Look for fields with title and empty value
        example = $('input[title]');
        example.bind('focus',{},function(){SearchFormClass.dropDefaultValue(this);});
        example.bind('blur',{},function(){SearchFormClass.setDefaultValue(this);});
        $.each(example,function(index,item){
            SearchFormClass.setDefaultValue(item);
        });

        SearchFormClass.form.submit(function(){
            id = $(this).find('input[name="id"]');
            if (1 == id.length && null == id.val().match(/^\d+$/g)) {
                id.attr('disabled','disabled');
            }

            $(this)
                .find('input[value="' + SearchFormClass.settings.emptyElement + '"], select[value="' + SearchFormClass.settings.emptyElement + '"]')
                .attr('disabled','disabled');

            return true;
        });
    }
};

function SearchForm(form, settings) {
    SearchFormClass = $.extend(true, SearchFormClass, settings);

    if (!SearchFormClass.form) {
        // Set search form object
        SearchFormClass.form = (typeof(form) == "object") ? form : $('#'+form);

        // Clear all binds for town field
        $('#town').unbind();

        // Set objects event processors
        $.each(SearchFormClass.settings.levels.list, function(index,level){
            $('#' + level).unbind().bind('change',{},function(){
                return SearchFormClass.changeLevel(level);
            });
        });

        $('#' + SearchFormClass.settings.levels.list[0]).removeAttr('disabled').parent('div').removeClass('disabled');
        SearchFormClass.autocomplete = $("#town").autocomplete(SearchFormClass.settings.autocomplete);
        SearchFormClass.init();
        SearchFormClass.initAutocomplete();

        // Settings for current country flash map load
        if(null !== SearchFormClass.currentFlash.country) {
            FlashMap.countryId = SearchFormClass.currentFlash.country;
        } else {
            SearchFormClass.predefineCounty();
        }

        // Settings for using region flash map instead of general country one
        if(null === SearchFormClass.currentFlash.region) {
            FlashMap.show(SearchFormClass.settings.flashMap);
            FlashMap._noFlashUpdate = false;
        } else {
            FlashMap.showRegion(SearchFormClass.currentFlash.region, SearchFormClass.settings.flashMap);
            FlashMap._noFlashUpdate = false;
        }
    }

    return SearchFormClass;
};


