/*
 * Fuel UX Combobox
 * https://github.com/ExactTarget/fuelux
 *
 * Copyright (c) 2012 ExactTarget
 * Licensed under the MIT license.
 */

define(['require','jquery','./util'],function (require) {

	var $   = require('jquery');
	var old = $.fn.combobox;
	require('./util');

	// COMBOBOX CONSTRUCTOR AND PROTOTYPE

	var Combobox = function (element, options) {
		this.$element = $(element);
		this.options = $.extend({}, $.fn.combobox.defaults, options);
		this.$element.on('click', 'a', $.proxy(this.itemclicked, this));
		this.$element.on('change', 'input', $.proxy(this.inputchanged, this));
		this.$input = this.$element.find('input');
		this.$button = this.$element.find('.btn');

		// set default selection
		this.setDefaultSelection();
	};

	Combobox.prototype = {

		constructor: Combobox,

		selectedItem: function () {
			var item = this.$selectedItem;
			var data = {};

			if (item) {
				var txt = this.$selectedItem.text();
				data = $.extend({ text: txt }, this.$selectedItem.data());
			}
			else {
				data = { text: this.$input.val()};
			}

			return data;
		},

		selectByText: function (text) {
			var selector = 'li:fuelTextExactCI(' + text + ')';
			this.selectBySelector(selector);
		},

		selectByValue: function (value) {
			var selector = 'li[data-value="' + value + '"]';
			this.selectBySelector(selector);
		},

		selectByIndex: function (index) {
			// zero-based index
			var selector = 'li:eq(' + index + ')';
			this.selectBySelector(selector);
		},

		selectBySelector: function (selector) {
			var $item = this.$element.find(selector);

			if (typeof $item[0] !== 'undefined') {
				this.$selectedItem = $item;
				this.$input.val(this.$selectedItem.text());
			}
			else {
				this.$selectedItem = null;
			}
		},

		setDefaultSelection: function () {
			var selector = 'li[data-selected=true]:first';
			var item = this.$element.find(selector);

			if (item.length > 0) {
				// select by data-attribute
				this.selectBySelector(selector);
				item.removeData('selected');
				item.removeAttr('data-selected');
			}
		},

		enable: function () {
			this.$input.removeAttr('disabled');
			this.$button.removeClass('disabled');
		},

		disable: function () {
			this.$input.attr('disabled', true);
			this.$button.addClass('disabled');
		},

		itemclicked: function (e) {
			this.$selectedItem = $(e.target).parent();

			// set input text and trigger input change event marked as synthetic
			this.$input.val(this.$selectedItem.text()).trigger('change', { synthetic: true });

			// pass object including text and any data-attributes
			// to onchange event
			var data = this.selectedItem();

			// trigger changed event
			this.$element.trigger('changed', data);

			e.preventDefault();
		},

		inputchanged: function (e, extra) {

			// skip processing for internally-generated synthetic event
			// to avoid double processing
			if (extra && extra.synthetic) return;

			var val = $(e.target).val();
			this.selectByText(val);

			// find match based on input
			// if no match, pass the input value
			var data = this.selectedItem();
			if (data.text.length === 0) {
				data = { text: val };
			}

			// trigger changed event
			this.$element.trigger('changed', data);

		}

	};


	// COMBOBOX PLUGIN DEFINITION

	$.fn.combobox = function (option) {
		var args = Array.prototype.slice.call( arguments, 1 );
		var methodReturn;

		var $set = this.each(function () {
			var $this   = $( this );
			var data    = $this.data( 'combobox' );
			var options = typeof option === 'object' && option;

			if( !data ) $this.data('combobox', (data = new Combobox( this, options ) ) );
			if( typeof option === 'string' ) methodReturn = data[ option ].apply( data, args );
		});

		return ( methodReturn === undefined ) ? $set : methodReturn;
	};

	$.fn.combobox.defaults = {};

	$.fn.combobox.Constructor = Combobox;

	$.fn.combobox.noConflict = function () {
		$.fn.combobox = old;
		return this;
	};


	// COMBOBOX DATA-API

	$(function () {
		$(window).on('load', function () {
			$('.combobox').each(function () {
				var $this = $(this);
				if ($this.data('combobox')) return;
				$this.combobox($this.data());
			});
		});

		$('body').on('mousedown.combobox.data-api', '.combobox', function () {
			var $this = $(this);
			if ($this.data('combobox')) return;
			$this.combobox($this.data());
		});
	});
});