(function($) {
    $.fn.location_landmark = function(o) {
        return this.each(function() {
            new $location_landmark($(this), o);
        });
    };

    // Default configuration properties.
    var defaults = {
		'type': [],
		'important' : 1,
		'suggest_limit' : 20,
		'search_limit' : 50,
		'limit' : 150,
		'select_text' : '- Выберите ориентир -',
		'select_other_text' : '- Другой -',
		'select_tree' : 0,
		'suggest_text' : 'Название ориентира...',

		'code': '',
		'parent': '',
		
		'result': 'Landmark',
		'input': 'LandmarkText',
		
		'onSelect' : false
	};


    $.location_landmark = function(e, o) {

		var self = this;
		this.options    = $.extend({}, defaults, o || {});

		this.container = e;
		this.code = '';
		this.cache = {};
		
		if ( typeof(this.options.onSelect) == "string" && this.options.onSelect != "" )
			this.onSelect = new Function("code", this.options.onSelect);
		
		this.restoreEnv();
		
		if ( o.reload == true )
			this.setupList($('.location-landmark-c', this.container));
    };

    // Create shortcut for internal use
    var $location_landmark = $.location_landmark;

    $location_landmark.fn = $location_landmark.prototype = {
        location_landmark: '0.0.1'
    };

    $location_landmark.fn.extend = $location_landmark.extend = $.extend;

    $location_landmark.fn.extend({
	
        restoreEnv: function() {
			var self = this;

			$('[class*="location-landmark-s"]', this.container).each(function(i, v) {
				self.registerSuggest($(v), self.options.parent);
				v.value = self.options.suggest_text;
				
				$(v).one('focus', function() {
					if (defaults.suggest_text == this.value)
						this.value = '';
				});
				$(v).bind('change', function() {
					if ( this.value == '')
						self.setCode(0);
				});
			});

			$('[class*="location-landmark-o"]', this.container).bind('change', function() {

					if ($location_landmark.intval(this.value) != -1) {

						var option = $(this.options[this.selectedIndex]);

						return self.changeLocation({
							code: this.value,
							name: this.options[this.selectedIndex].text,
							type: option.attr('_type')
						});
					}
					
					self.createSuggest(self.options.parent);
			});
        },

		createSuggest: function(code) {
			var container = $('.location-landmark-c', this.container);
			var suggest = $('<input type="text"/>');
			suggest
				.addClass('suggest').addClass('location-landmark-s').attr('name',this.options.input)
				.bind('change', function() {
					if ( this.value == '')
						self.setCode(0);
				});
				
			this.registerSuggest(suggest, code);

			$('*', container).remove();
			container.append(suggest);			
		},

		registerSuggest: function(suggest, code) {

			var self = this;

			suggest.val('');
			suggest.autocomplete("/service/source/db.location_landmarks", {
				dataType: 'json',
				extraParams: {
					parent: code,
					type_in: this.options.type,
					limit: this.options.suggest_limit,
					type: 'query'
				},
				parse: function(json) {
					var parsed = [];

					if ( !json.list || !json.list.length )
						return parsed;

					for (var i in json.list) {
						if ( typeof json.list[i] != 'object' )
							continue;

						parsed[parsed.length] = {
							data: json.list[i].name,
							value: json.list[i]
						};
					}

					return parsed;
				},
				formatItem: function(text, i, max, value) {
					var Desc = '';
					if ( value.parent && value.parent.length ) {
						Desc = '<div class="ac_describe">';
						for (var j in value.parent)
						{
							if ( typeof value.parent[j] == 'string' )
								Desc += value.parent[j] + '<br />';
						}
						Desc += '</div>';
					}
					return value.name + Desc;
				},
				returnFocus: false,
				max: this.options.suggest_limit
			}).result(function(event, name, value) {
				return self.changeLocation({
					name: value.name.replace(/<.*>/, ''),
					code: value.id,
					type: value.type
				});
			});
		},

		setupList: function(container) {
			$('*', container).remove();
			
			this.showLoader(container);
			var self = this;
			var parent = this.options.parent;
			
			if (typeof this.cache[parent] == 'object')
				return self.loadListSuccess(this.cache[parent], parent, container);

			$.ajax({
				mode: 'abort',
				port: 'list_landmark',
				type: 'POST',
				url: '/service/source/db.location_landmarks',
				dataType: 'json',
				data: {
					parent: parent,
					important: this.options.important,
					limit: this.options.limit,
					type: 'subordinate_landmarks',
					tree: this.options.select_tree
				},

				error: function() {
					if (confirm("Не удалось получить список.\nПовторить?"))
						self.setupList(container);
				},

				success: function(json) {
					self.loadListSuccess(json, parent, container);
				}
			});
		},

		loadListSuccess: function(json, parent, container) {
			var self = this;
			var limit = parseInt(this.options.limit);
			var search_limit = parseInt(this.options.search_limit);

			if (!limit || parseInt(json.count) <= limit) {

				var list = $('<select/>');
				list
					.addClass('list').addClass('location-landmark-o');

				list.bind('change', function() {

					if ($location_landmark.intval(this.value) != -1) {

						var option = $(this.options[this.selectedIndex]);

						return self.changeLocation({
							code: this.value,
							name: this.options[this.selectedIndex].text,
							type: option.attr('_type')
						});
					}

					self.createSuggest(parent);
				});

				list.append($('<option/>').attr({value: undefined}).html(this.options.select_text));

				var group = null;
				var _type = 0;

				jQuery.each(json.list, function(i, v) {
					if ( self.options.select_tree && v.type != _type )	{
						group = $('<optgroup></optgroup>').attr({ label: json.types[parseInt(v.type)].SocrText });
						list.append(group);
						_type = v.type;
					}
					
					var option = $('<option></option>').attr({
							value: v.id,
							_type: v.type
						}).html(v.name);
					
					if ( self.options.select_tree ) {
						group.append(option);
					} else {
						list.append(option);
					}					
				});

				if (this.options.important)
					list.append($('<option></option>').val(-1).html( self.options.select_other_text ).css('font-weight','bold'));

				container.append(list);

				if (this.cache[parent] == undefined)
					this.cache[parent] = json;
			} else
				this.createSuggest(parent);
			
			this.removeLoader();
		},

		changeLocation: function(params) {			
			$('.location-landmark-s', this.container).val(params.name);
			this.setCode(params.code);
			
			if ( typeof(this.onSelect) == "function" ) {
				try {
					this.onSelect(params.code);
				} catch(e) {}
			}
		},

		showLoader: function(container) {
			
			this.removeLoader();
			
			var loader = $('<input type="text" />');
			loader.attr({
				readonly: true, disabled: true,
				value: 'Загрузка...'
			}).addClass('loader');

			container.append(loader);
		},

		removeLoader: function() {
			$('.loader', this.container).remove();
		},

		setCode: function(code) {
			var input = $('.location-landmark-v', this.container);

			input.val(code);

			return code;
		},

		objectCode: function(code) {
			return new Array(
				code.substr(0, 3) ? code.substr(0, 3) : '000',
				code.substr(3, 3) ? code.substr(3, 3) : '000',
				code.substr(6, 3) ? code.substr(6, 3) : '000',
				code.substr(9, 3) ? code.substr(9, 3) : '000',
				code.substr(12, 3) ? code.substr(12, 3) : '000',
				code.substr(15, 3) ? code.substr(15, 3) : '000',
				code.substr(18, 4) ? code.substr(18, 4) : '0000'
			);
		}

    });

    $location_landmark.extend({
        defaults: function(d) {
            return $.extend(defaults, d || {});
        },

        intval: function(v) {
            v = parseInt(v);
            return isNaN(v) ? 0 : v;
        }
    });
	
})(jQuery);
