YUI.add('package', function(Y) {
	
	function Package() {
		Package.superclass.constructor.apply(this, arguments);
	}

	// Hyphen-ated
	Package.NAME = 'package';

	// camelCase
	Package.NS = 'package';

	Package.ATTRS = {

		description: {
			value: false
		},
		
		descriptionLength: {
			value: 0
		},
		
		editMagDescHandle: {
			value: false
		},
		
		selectboxHandle: {
			value: false
		},

		textareasHandle: {
			value: false
		},

		textareaOnkeyupHandle: {
			value: false
		},
		
		saveButtonsHandle: {
			value: false
		},
		
		extraMagazinesHandle: {
			value: false
		},
		
		addonsHandle: {
			value: false
		},
		
		currentPricingId: {
		},
		
		extraMagazinesPrice: {
			value: 0
		},
		
		addonsPrice: {
			value: 0
		},
			
		hasEditedDescription: {
		},
			
		packages: {
		},
		
		magazinePricing: {
		},
		
		extraMagazinesSelected: {
			value: new Array()
		},
	
		selectBox: {
		},
		
		charCount: {
			value: 0
		},
		
		adPrice: {
			valueFn: function() {
				return this.get('host').one('.priceInt');
			}
		},
		
		pricePerWeek: {
			valueFn: function() {
				return false;
			}
		},
		
		radioButtons: {
			valueFn: function() {
				return this.get('host').all('input[type=radio]');
			},
			readOnly: true
		},

		selectedPackage: {
			valueFn: function() {
				var selected;
				this.get('radioButtons').some(function(node) {
					if (node.get('checked')) {
						selected = node;
						return false;
					}
				});
				return selected;
			},
			readOnly: false
		},
		
		numberOfWeeks: {
			valueFn: function() {
				return this.get('host').one('#numWeeksSelect').get('value');
			}
		}
	};

	Y.extend(Package, Y.Plugin.Base, {

		initializer: function() {
		
			if(this.validatePackages()){
				
				this.get('host').all('.js-remove').remove();
				
				this.get('host').all('.noscript-hidden').setStyle('display', 'inline');
				
				this.get('host').all('.editNotice').setStyle('display', 'none');
				
				this.get('host').all('.editMagDescButton').setStyle('display', 'none');
				
				if(this.getSelectedPackage()){
					this.set('pricePerWeek', (this.getNextPricePerWeek(this.getSelectedPackage()) - this.getCurrentPricePerWeek(this.getSelectedPackage())));
					this.getAdDescription();
				}
				
				if(this.get('pricePerWeek') === false) {
					this.get('host').one('#extraWeek').setStyle('display', 'none');
				} else {
					if(this.getSelectedPackage()){
						this.updatePricePerWeek();
					}
				}

				/* delegate event listeners */
				this.set('editMagDescHandle', Y.delegate('click', this._handleEditMagDescClick, this.get('host'), '.editMagDescButton', this));
				this.set('textareasHandle', Y.delegate('click', this._handleRadioButtonClick, this.get('host'), 'input[type=radio]', this));
				this.set('selectboxHandle', Y.one('select').on('change', this._handleSelectBoxChange, this));
				this.set('saveButtonsHandle', Y.delegate('click', this._handleAjaxSaveButtonClick, this.get('host'), '.ajaxSaveButton', this));
				this.set('textareaOnkeyupHandle', Y.delegate('keyup', this._handleTextareaOnkeyup, this.get('host'), '.dynamicTextarea', this));
				this.set('extraMagazinesHandle', Y.delegate('click', this._handleExtraMagazinesClick, this.get('host'), '.extraMagazine', this));
				this.set('addonsHandle', Y.delegate('click', this._handleAddonsClick, this.get('host'), '.addon', this));
				
				/* create change handlers */
				this.on('selectedPackageChange', this._handleSelectedPackageChange);
				
				/* create hidden post field for form to know that js is active */
				this.get('host').insert('<input type="hidden" name="js-active" value="1" />');
				
				/* if there's a selected package and the description exceeds the limit then open up an editor */
				if(this.getSelectedPackage() !== false){
					this._set('selectedPackage', this.getSelectedPackage());
				}/**/
			}
		},

		_handleDynamicTextareaChange: function(event){
			
		},
		
		_handleExtraMagazinesClick: function(event){
			if(this.updateExtraMagazinesPrice() === true){
				this.updateAdPrice();
			}
		},
		
		_handleAddonsClick: function(event){
			if(this.updateAddonsPrice() === true){
				this.updateAdPrice();
			}
		},
		
		_handleRadioButtonClick: function(event) {
			Y.all('.editMagDescButton').setStyle('display','none');
			this._set('selectedPackage', event.target);
		},

		_handleSelectedPackageChange: function(event) {
			var newPricingId = event.newVal.get('value');
			var oldPricingId = this.get('currentPricingId');
			
			this.set('pricePerWeek', (this.getNextPricePerWeek(event.newVal) - this.getCurrentPricePerWeek(event.newVal)));
			this.refreshSelectbox();
			this.refreshEditBoxes(event.newVal);
			this.updateUpgradeOption(event.newVal);
			var updatedAddons = this.updateAddons(oldPricingId, newPricingId);
			if(this.updateExtraMagazines(event.newVal) || updatedAddons){
				this.updateAdPrice();
			}
			
			this.set('currentPricingId', newPricingId);
		},
		
		_handleEditMagDescClick: function(event) {
			this.refreshEditBoxes(this.get('host').one('#adPackageId' + event.target.get('id').substr(11)), 'CREATE');
		},
		
		_handleSelectBoxChange: function(event) {
			var newValue;
			if(this.getSelectedPackage() === false) {
				return false;
			}
			newValue = event.target.get('value');
			this.set('numberOfWeeks', newValue);
			this.updateUpgradeOption();
			this.updateAdPrice();
		},
		
		_handleTextareaOnkeyup: function(event) {
			var newLength = event.target.get('value').length;
			this.updateCharCounter(newLength);
		},
		
		_handleAjaxSaveButtonClick: function(event){
			this.set('hasEditedDescription', true);
			this.setDescriptionByPOST(encodeURI(Y.one('#dynamicTextarea' + event.target.get('id').substr(14)).get('value')));
		},

		_handleGetPOSTSuccess: function(ioId, o){
			Y.all('.dynamicTextarea').set('value',o.responseText);
			this.set('description', o.responseText);
			this.updateCharCounter(o.responseText.length);
		},
 
		_handleGetPOSTFailure: function(ioId, o){
			Y.log("The failure handler was called");
			Y.log("Transaction id: " + ioId);
			Y.log("HTTP status: " + o.status);
			Y.log("Status code message: " + o.statusText);
		},

		_handleSetPOSTSuccess: function(ioId, o){
			var thisPackage,targetId;
			thisPackage = this.getSelectedPackage();
			targetId = thisPackage.get('id').substr(11);
			this.refreshEditBoxes(thisPackage, 'CLOSE');
			this.getParentLi(targetId).insert('<p class="saveSuccess" id="saveSuccess' + targetId + '">Changes saved</p>');
			Y.one('#editMagDesc'+targetId).setStyle('display', 'inline');
		},
 
		_handleSetPOSTFailure: function(ioId, o){
			Y.log("The failure handler was called");
			Y.log("Transaction id: " + ioId);
			Y.log("HTTP status: " + o.status);
			Y.log("Status code message: " + o.statusText);
		},
		
		makeRequest: function(cfg, sUrl, onSuccess, onFailure){

			Y.once('io:success', onSuccess, this);
			Y.once('io:failure', onFailure, this);
	 
			function makeRequest(){
				Y.io(sUrl, cfg);
			}
			makeRequest();
		},
		
		getDescriptionByPOST: function(){
			var cfg,loc;
			loc = 'ajax.php';
			cfg = {
				method: "POST",
				data: "request=GET_DESCRIPTION_",
				headers: { 'X-Transaction': 'POST Request'}
			};
			this.makeRequest(cfg, loc, this._handleGetPOSTSuccess, this._handleGetPOSTFailure );
		},
		
		setDescriptionByPOST: function(parameters){
			var cfg, loc;
			loc = 'ajax.php';
			cfg = {
				method: "POST",
				data: "request=SET_DESCRIPTION_" + parameters,
				headers: { 'X-Transaction': 'POST Request'}
			};
			this.makeRequest(cfg, loc, this._handleSetPOSTSuccess, this._handleSetPOSTFailure );
		},
		
		getMaxWeeksOption: function(){
			var maxOption = 0;
			this.get('host').all('#numWeeksSelect option').each(function(e){
				maxOption = parseInt(e.get('value'), 10) > maxOption ? e.get('value') : maxOption;
			});
			return maxOption;
		},
		
		getSelectedPackage: function(){
			var selected;
			this.get('radioButtons').some(function(node) {
				if (node.get('checked')) {
					selected = node;
					return false;
				}
			});
			return selected !== undefined ? selected : false;
		},
		
		getNextWeeklyPriceArrayIndex: function(currentPackage){
			var next, i, len;
			next= false;
			i = 0;
			len = currentPackage.weeklyPrices.length;
			for( i; i < len; i++ ){
				if(next === true){
					return i;
				}
				if( currentPackage.weeklyPrices[i].weeks == this.getNumWeeksSelected()){
					next = true;
				}
			}
			return false;
		},
		
		getCurrentWeeksSelected: function(){
			return isNaN(this.getNumWeeksSelected()) ? 0 : this.getNumWeeksSelected();
		},
		
		getWeeklyPriceArrayIndex: function(){
			var currentWeeksSelected = this.getCurrentWeeksSelected(),currentPackage = this.get('packages')[this.getSelectedPackage().get('id').substr(11)], x;
			for( x in currentPackage.weeklyPrices ) {
				if (currentPackage.weeklyPrices.hasOwnProperty(x)){
					if(currentPackage.weeklyPrices[x].weeks == currentWeeksSelected){
						return x;
					}
				}
			}
			return false;
		},
		
		getNumWeeksSelected: function(){
			var selectVal = parseInt(this.get('host').one('#numWeeksSelect').get('value'), 10);
			if(selectVal === 0 || selectVal === undefined || selectVal === null) {
				selectVal = 1;
			}
			return selectVal;
		},
		
		getNextPricePerWeek: function(pkg){
			var currentPackage = (pkg === undefined || pkg === false) ? this.get('packages')[this.getSelectedPackage().get('id').substr(11)] : this.get('packages')[pkg.get('id').substr(11)];
			return ( currentPackage.weeklyPrices[this.getNextWeeklyPriceArrayIndex(currentPackage)] !== undefined ) ? currentPackage.weeklyPrices[this.getNextWeeklyPriceArrayIndex(currentPackage)].price : false;
		},
		
		getCurrentPricePerWeek: function(pkg){
			var packageIndex;
			if(pkg === undefined || pkg === false) {
				pkg = this.getSelectedPackage();
			}
			if(pkg === false) {
				return false;
			}
			packageIndex = pkg.get('id').substr(11);
			return this.getWeeklyPriceArrayIndex() !== false ? this.get('packages')[packageIndex].weeklyPrices[this.getWeeklyPriceArrayIndex()].price : false;
		},
		
		getCurrentPackageIndex: function(){
			return this.getSelectedPackage().get('id').substr(11);
		},
		
		getCurrentAdPrice: function(){
			this.updateAddonsPrice();
			return this.getCurrentPricePerWeek() + this.getExtraMagazinesPrice() + this.get('addonsPrice');
		},
		
		getCurrentPackageTitle: function(){
			var packageIndex = this.getSelectedPackage().get('id').substr(11);
			return this.get('packages')[packageIndex].title;
		},
		
		getExtraMagazinesPrice: function(){
			return this.get('extraMagazinesPrice', 0);
		},
		
		getAdDescription: function(){
			this.getDescriptionByPOST();
		},
		
		getParentLi: function(targetId){
			return this.get('host').one('#adPackageId' + targetId).get('parentNode').get('parentNode');
		},
		
		checkDescriptionLength: function(pkg){ // returns true if description is within limits
			var descLength, thisPackage;
			thisPackage = this.get('packages')[pkg.get('id').substr(11)];
			descLength = (this.get('description').length === undefined) ? this.get('descriptionLength') : this.get('description').length;
			return descLength <= thisPackage.descriptionLimit ? true : false;
		},
		
		toggleUpgradeOption: function(show) {
			var show = (show)?true:false, state = 'none';
			if(show === true){
				state = 'block';
			}
			this.get('host').one('#upgradeNotice').setStyle('display', state);
			return false;
		},
		
		updateUpgradeOption: function(pkg){
			var package_id = (pkg !== undefined) ? pkg.get('id').substr(11) : this.getCurrentPackageIndex(),currentWeeksSelected = this.getCurrentWeeksSelected(), weeklyPrices = new Array(), i = 0, weeklyPricesIndex = 0, upgradePackageId = 0,upgradePackageTitle = '';
			
			// is there an upgrade option? if not, hide the option
			if(this.get('packages')[package_id - 1] === undefined){
				this.toggleUpgradeOption(false);
				return false;
			}
			
			upgradePackageTitle = (this.get('packages')[package_id - 1].title !== undefined) ? this.get('packages')[package_id - 1].title : '';
			upgradePackageIndex = (package_id - 1 > 0) ? (package_id - 1).toString() : '0';
			
			weeklyPrices = (this.get('packages')[package_id - 1].weeklyPrices !== undefined) ? this.get('packages')[package_id - 1].weeklyPrices : false;
			if(weeklyPrices !== false){
				// this code assumes that you will not be able to upgrade to a package that offers less weeks than the existing package
				for(i in weeklyPrices){
					if (weeklyPrices.hasOwnProperty(i)){
						if(parseInt(weeklyPrices[i].weeks) === parseInt(currentWeeksSelected) || parseInt(weeklyPrices[i].weeks) > parseInt(currentWeeksSelected)){
							weeklyPricesIndex = i;
							break;
						}
					}
				}
				
				this.get('host').one('#upgradeNotice .upgradePackage').set('innerHTML', upgradePackageTitle);
				if(upgradePackageId !== false){
					this.get('host').one('#upgradeNotice .upgradePackage').set('href', '?step=2&incrementPackage=' + upgradePackageIndex + '&weeks=' + currentWeeksSelected.toString());
				}
				this.get('host').one('#upgradeNotice .upgradeCost').set('innerHTML', (weeklyPrices[weeklyPricesIndex].price - this.getCurrentPricePerWeek()).toString());
				
				// make sure the upgrade option is displayed
				this.toggleUpgradeOption(true);
			}
			return false;
		},
		
		updateExtraMagazines: function(pkg){
			var i, periodTxt = '', totalPrice = 0, extraMagazines = false, checked = false, stateArray = new Array(), magazineName = '';
		
			if(this.get('magazinePricing') !== undefined && this.get('magazinePricing')[0] !== undefined){
				extraMagazines = eval("this.get('magazinePricing')[0].pricing" + this.get('packages')[pkg.get('id').substr(11)].id);
			} else {
				// there are no prices to update, so return true
				return true;
			}
		
			this.get('host').all('.extraMagazine input').each(function(e){
				stateArray[e.get('name')] = (e.get('checked') === true) ? 'checked' : '';
			});
			this.set('extraMagazinesSelected', stateArray);
			this.get('host').one('#extraMagazines').set('innerHTML', '');
			if(extraMagazines !== null ){
				for(i in extraMagazines){
					if (extraMagazines.hasOwnProperty(i)){
						magazineName = 'extraMagazine'+extraMagazines[i].magazine;
						if(this.get('extraMagazinesSelected')[magazineName] === 'checked'){
							totalPrice += extraMagazines[i].price;
						}
						periodTxt = (extraMagazines[i].period === 'monthly') ? '(1 month)' : '';
						if(this.get('host').one('#extraMagazine'+extraMagazines[i]) === null){
							this.get('host').one('#extraMagazines').append('<p id="extraMagazine'+extraMagazines[i].magazine+'" class="extraMagazine">Place your ad in <strong>'+extraMagazines[i].magazine.replace('-',' ')+'</strong> magazine for <span class="extraMagazinePrice">just &pound;'+extraMagazines[i].price.toString()+'</span>&nbsp;<input type="checkbox" value="1" class="extraMagazineCheck" name="'+magazineName+'" '+this.get('extraMagazinesSelected')[magazineName]+'/> '+periodTxt+'</p>');
						}
					}
				}
			}
			this.set('extraMagazinesPrice', totalPrice);
			return true;
		},
		
		updateAddons: function(previousPricingId, newPricingId){
			var updatedPackage = false;
			
			// Has anything changed?
			if(previousPricingId != newPricingId) {
				// Go through each pricegroup
				Y.all('.priceGroup').each(function() {
					if(this.get('id') == 'priceGroupId'+newPricingId) {
						// Show the new one
						this.removeClass('hidden');
					} else {
						// Hide the other ones
						this.addClass('hidden');
					}
				});
				// Return whether we updated
				updatedPackage = true;
			}
			
			return updatedPackage;
		},
		
		updateExtraMagazinesPrice: function(){
			var totalPrice = 0;
			this.get('host').all('.extraMagazine').each(function(e){
				if(e.one('.extraMagazineCheck').get('checked') === true){
					totalPrice += parseInt(e.one('.extraMagazinePrice').get('innerHTML').match(/\d+/));
				}
			});
			this.set('extraMagazinesPrice', totalPrice);
			return true;
		},
		
		updateAddonsPrice: function(){
			var totalPrice = 0;
			this.get('host').all('.addon').each(function(e){
				isHidden = e.one('.addonCheck').ancestors(function(anc) {return anc.hasClass('hidden');}, true).size() > 0;
				if(isHidden !== true){
					if(e.one('.addonCheck').get('checked') === true){
						totalPrice += parseInt(e.one('.addonPrice').get('innerHTML').match(/\d+/));
					}
				}
			});
			this.set('addonsPrice', totalPrice * this.getNumWeeksSelected());
			return true;
		},
		
		updateAdPrice: function(){
			var currentPrice, price;
			currentPrice = (this.getCurrentAdPrice() !== null) ? this.getCurrentAdPrice() : 0;
			this.updatePricePerWeek();
			this.get('host').all('.currentAdPackageTitle').set('innerHTML', this.getCurrentPackageTitle());
			price = (currentPrice > 0) ? currentPrice.toString() : ' free';
			this.get('host').one('#priceInt').set('innerHTML', price);
		},
		
		updatePricePerWeek: function(){
			var pricePerWeek, pricePerWeekText, currentPackage;
			currentPackage = this.get('packages')[this.getCurrentPackageIndex()];
			pricePerWeek = this.getCurrentPricePerWeek(this.getSelectedPackage());
			if(this.getNextPricePerWeek() === false){
				this.get('host').one('#extraWeek').setStyle('display','none');
			} else {
				this.set('pricePerWeek', (this.getNextPricePerWeek(this.getSelectedPackage()) - pricePerWeek));
				if(this.get('pricePerWeek') > 0){
					if((currentPackage.weeklyPrices[this.getNextWeeklyPriceArrayIndex(currentPackage)].weeks - this.getNumWeeksSelected()) == 1){
						pricePerWeekText = 'Add an extra week for just <strong>&pound;' + this.get('pricePerWeek') + '</strong>';
					} else {
						pricePerWeekText = 'Add ' + (currentPackage.weeklyPrices[this.getNextWeeklyPriceArrayIndex(currentPackage)].weeks - this.getNumWeeksSelected()).toString() + ' extra weeks for just <strong>&pound;' + this.get('pricePerWeek') + '</strong>';
					}
				} else {
					pricePerWeekText = 'Add an extra week free';
				}
				this.get('host').one('#extraWeek').set('innerHTML','<span class="pricePerWeek"></span>');
				this.get('host').one('#extraWeek').setStyle('display','block');
				this.get('host').all('.pricePerWeek').set('innerHTML', pricePerWeekText);
			}
		},
		
		createTextarea: function(pkg){
			var nodeID, parentLi, expandArea;
			nodeID = '#dynamicTextarea' + pkg.get('id').substr(11);
			this.getAdDescription();
			parentLi = this.getParentLi(pkg.get('id').substr(11));
			if(this.get('host').one('#editNotice' + pkg.get('id').substr(11)) !== null){
				this.get('host').one('#editNotice' + pkg.get('id').substr(11)).setStyle('display', 'inline');
			}
			parentLi.insert('<textarea class="dynamicTextarea" id="dynamicTextarea' + pkg.get('id').substr(11) + '"></textarea>');
			parentLi.insert('<p class="charCounter" id="charCounter' + pkg.get('id').substr(11) + '">Characters used: <span></span></p>');
			expandArea = new Y.Anim({
		        node: nodeID,
		        from: { height: 0 },
		        to: { height: 70 },
		        duration: 0.5,
		        easing: Y.Easing.easeOut
			});
			expandArea.run();
		},
		
		createSaveButton: function(pkg){
			pkg.get('parentNode').get('parentNode').insert('<span class="ajaxSaveButton" id="ajaxSaveButton' + pkg.get('id').substr(11) + '">Save changes</span>');
		},
		
		destroySaveButtons: function(){
			Y.all('.ajaxSaveButton').remove();
		},
		
		updateCharCounter: function(newLength) {
			
			var targetElement, targetId, charLimit, remainingChars;
			targetElement = this.getSelectedPackage();
			targetId = targetElement.get('id').substr(11);
			
			if(newLength === false){
				newLength = this.get('host').one('#dynamicTextarea'+targetId).get('value').length;
			}
			
			charLimit = parseInt(this.get('packages')[targetId].descriptionLimit, 10);
			remainingChars = charLimit - newLength;
			this.get('host').all('.charCounter span').set('innerHTML', newLength);
			if(newLength <= this.get('packages')[targetId].descriptionLimit){
				if(this.get('host').one('#charCounter'+targetId)!==null){
					this.get('host').one('#charCounter'+targetId).set('innerHTML', 'You have used <span>' + newLength + '</span> of ' + charLimit + ' characters');
				}
				this.get('host').all('.charCounter span').setStyle('color', '#000');
				if(!Y.one('.ajaxSaveButton') && Y.one('#dynamicTextarea'+targetId)) {
					this.createSaveButton(targetElement);
				}
			} else {
				this.get('host').one('#charCounter'+targetId).set('innerHTML', 'You have exceeded the character limit for a ' + this.getParentLi(targetId).one('.ad-info label').get('innerHTML') + ' advert. Characters remaining: <span>' + remainingChars + '</span>');
				this.get('host').all('.charCounter span').setStyle('color', '#f00');
				this.destroySaveButtons();
			}
			
		},
		
		hideUnwantedElements: function(name, pkg, forceClose){
			this.get('host').all('.'+name).each(function(e){
				if(pkg.get('id').substr(11) != e.get('id').substr(name.length) || forceClose){
					e.setStyle('display','none');
				}
				
			});
			
		},
		
		removeUnwantedElements: function(name, pkg, forceClose){
			this.get('host').all('.'+name).each(function(e){
				if(pkg.get('id').substr(11) != e.get('id').substr(name.length) || forceClose){
					e.remove();
				}
			});
		},
		
		destroyTextareas: function(){
			Y.all('.dynamicTextarea').remove();
			Y.all('.charCounter').remove();
		},
		
		refreshSelectbox: function(){
			var currentPackage, currentWeeksSelected, s, selected, first, i, len;
			currentPackage = this.get('packages')[this.getCurrentPackageIndex()];
			currentWeeksSelected = this.getNumWeeksSelected();
			s = '';
			first = true;
			i = 0;
			len = currentPackage.weeklyPrices.length;
			this.get('host').one('#numWeeksSelect').set('innerHTML', '');
			for( i; i < len; i++ ){
				if(currentWeeksSelected == currentPackage.weeklyPrices[i].weeks || (currentWeeksSelected === false && first === true)){
					selected = i;
				}
				s = currentPackage.weeklyPrices[i].weeks != 1 ? 's' : '';
				this.get('host').one('#numWeeksSelect').append('<option value="'+currentPackage.weeklyPrices[i].weeks+'">'+currentPackage.weeklyPrices[i].weeks+' week'+s+'</option>');
				first = false;
			}
			this.get('host').one('#numWeeksSelect').set('selectedIndex', selected);
		},
		
		refreshEditBoxes: function(pkg, force){
						
			var targetId, forceCreate, forceClose;
			
			targetId = pkg.get('id').substr(11);
			
			if(force == 'CREATE'){
				forceCreate = true;
			} else {
				forceCreate = false;
			}

			if(force == 'CLOSE'){
				forceClose = true;
			} else {
				forceClose = false;
			}
			
			/* iterate over textareas and close them all */
			this.get('host').all('.dynamicTextarea').each(function(e){
				var endFunc, contractArea;				
				if(e.get('id').substr(15) != targetId || forceClose) {
					endFunc = function(){
						this.set('description', e.get('value'));
						e.remove();
					};
					contractArea = new Y.Anim({
						node: '.dynamicTextarea',
						from: { height: 70 },
				        to: { height: 0 },
				        duration: 0.5,
				        easing: Y.Easing.easeOut
					});
					contractArea.on('end', endFunc);
					contractArea.run();
				}
			});
			
			this.removeUnwantedElements('charCounter', pkg, forceClose);

			this.removeUnwantedElements('ajaxSaveButton', pkg, forceClose);

			this.removeUnwantedElements('saveSuccess', pkg, true);
			
			this.hideUnwantedElements('editNotice', pkg, forceClose);
			
			// if this package is online only then abort now
			if(this.get('packages')[targetId].onlineOnly){
				return false;
			}
			
			/* open or close the current elements as appropriate */
			if(forceCreate === true || (this.checkDescriptionLength(pkg) === false && this.get('host').one('#dynamicTextarea'+targetId) === null)){
				Y.all('.editMagDescButton').setStyle('display', 'none');
				this.createTextarea(pkg);
			} else {
				if(Y.one('#dynamicTextarea'+targetId) === null && this.get('hasEditedDescription')){
					Y.one('#editMagDesc'+targetId).setStyle('display', 'inline');
				}
				if(this.checkDescriptionLength(pkg)){
					this.destroyTextareas();
				}
			}
		},
		
		validatePackages: function(){
			var i;
			if(this.get('packages') === undefined){
				Y.log('Packages undefined');
				return false;
			}
			if(this.get('packages')[0] === undefined){
				Y.log('Packages[0] undefined');
				return false;
			}
			i = 0;
			while(this.get('packages')[i] !== undefined){
				if(isNaN(parseInt(this.get('packages')[i].id, 10))){
					Y.log('packages['+i+'].id invalid');
					return false;
				}
				if(isNaN(parseInt(this.get('packages')[i].pricePerWeek, 10))){
					Y.log('packages['+i+'].pricePerWeek invalid');
					return false;
				}
				if(isNaN(parseInt(this.get('packages')[i].descriptionLimit, 10))){
					Y.log('packages['+i+'].descriptionLimit invalid');
					return false;
				}
				if(this.get('packages')[i].exceedsLength !== 0 && this.get('packages')[i].exceedsLength != 1){
					Y.log('packages['+i+'].exceedsLength invalid');
					return false;
				}
				i++;
			}
			return true;
		}
	});

	Y.namespace('IPC.HHO.AdBooking.Plugin');
	Y.IPC.HHO.AdBooking.Plugin.Package = Package;

}, '3.1.1', {requires: ['plugin']});
