function Quoter(buildingname, buildingnumber, thoroughfare, town, postcode){
	
	this.buildingName = buildingname;
	this.buildingNumber = buildingnumber;
	this.thoroughfare = thoroughfare;
	this.town = town;
	this.postcode = postcode;
	
	this.numberOfTenants = 5;
	this.startDate = Date();
	this.minTerm = 12;
	this.greenEnergy = false;
	this.mac = '';
	
	this.service = {broadband: true, gas: true, water: true, telephone: true, elec: true, tv_license: true};
	
	this.prices = {broadband: '?', gas: '?', water: '?', telephone: '?', elec: '?', tv_license: '?'};
	
	this.cli = null;
	this.broadbandOption = null;
	this.broadbandOptions = null;

	this.telephoneConnectionType = null;
	this.telephoneConnectioncharge = null;
	this.broadbandActivationCharge = null;
	this.waterAvailable = null;
	
	this.verbose = false;
	this.ready = 0;
	this.waitingOnQuote = false;
	
	this.wlr3Addresses = new Array();
	this.wlr3AddressReference = '';
	
	
	this.init = function(){
		this.checkWaterAvailability();
		this.initBroadbandOptions();
		this.getBroadbandActivationCharge();
	}
	
	this.initBroadbandOptions = function(){
		var self = this;
		this.log("Initialising broadband options");
		$.ajax({
			type:		'POST',
			data:		{postcode: postcode},
			url:		'/ajax/broadband_lookup/',
			dataType:	'json',
			success: function(json) {
				self.initTelephoneConnectionType();
				self.log('Retrieved broadband options');
				for (var key in json) {
				    self.broadbandOption = key; //update the broadband option to the first one.
				    break;
				}
				$(window).trigger('broadbandOptionsLoaded', {options: json});
				self.broadbandOptions = json;
			},
			error:	function() {
				self.broadbandOptions = 'Server error please try again.'
			}
		});
	}
	
	this.checkWaterAvailability = function (){
		var self = this;
		this.log("Checking water availability");
		$.ajax({
			type:	'POST',
			data:	{service: 'water', tenants: this.numberOfTenants, period: this.minTerm, extra: this.postcode},
			url:	'/ajax/getServiceQuote/',
			dataType: 'json',
			success: function(json) {
				if(json.monthly_fee == '0.00'){
					self.service.water = false;
					self.waterAvailable = false;
					$(window).trigger('noWaterAvalability');
					self.log("No water available for postcode: "+self.postcode);
				}
			},
			error:	function() {
				error_dialog('Server error','We were unable to contact the server, please refresh the page and try again.');
			}
		});
	}
	
	this.initTelephoneConnectionType = function(){
		var self = this;
		var data = {postcode: this.postcode, town: this.town, thoroughfare: this.thoroughfare, addressReference: this.wlr3AddressReference}
		if(this.buildingName != ''){
			data['buildingname'] = this.buildingName;
		}else{
			data['buildingnumber'] = this.buildingNumber;
		}
		this.log("Initialising line connection type");
		$.ajax({
			type:		'POST',
			data:		data,
			url:		'/ajax/getTelephoneConnectionType/',
			dataType:	'json',
			success: function(json) {
				if(json == null || json.error != false){
					self.log('Could not find the address in wlr3');
					$(window).trigger('lineConnectionTypeUpdateFailed', {});
					self.getPossibleWLR3Addresses();
				}else{
					self.log('Retrieved line connection type: '+json['type']);
					self.telephoneConnectionType = json;
					self.updateConnectionCharge(function(json){});
					$(window).trigger('lineConnectionTypeUpdate', {options: json});
				}
			},
			error:	function() {
				self.log("Error getting the address from wlr3");
			}
		});
	}
	
	this.getPossibleWLR3Addresses = function(){
		var self = this;
		this.log('Retrieving all WLR3 available addresses');
		$.ajax({
			type:		'POST',
			data:		{postcode: this.postcode},
			url:		'/ajax/getWLR3Addresses/',
			dataType:	'json',
			success: function(data) {
				self.log('Retrived all available addresses');
				$(window).trigger('wlr3AddressesFetched', {addresses: data});
				self.wlr3Addresses = data;
			},
			error:	function() {
				self.log("Error getting the address from wlr3");
			}
		});
	}
	
	this.validatePostcode = function(callback){
		$.ajax({
			type:	'POST',
			data:	{postcode: this.postcode},
			url:	'/ajax/postcode_validate/',
			dataType: 'json',
			success: function(jsonObject) {
				callback(jsonObject.valid);
			},
			error:	function() {
				callback(false);
				error_dialog('Server error','We were unable to contact the server, please refresh the page and try again.');
			}
		});
	}
	
	this.recalculateQuote = function(){
		this.getBroadbandActivationCharge();
		if(this.ready != 0){
			this.waitingOnQuote = true;
			return;
		}else{
			$(window).trigger('retrievingQuote');
		}
		var self = this;
		this.ready = 8;
		this.updateServicePrice('gas', function(response){self.ready--;if(self.ready == 0) self.finishQuote();});
		this.updateServicePrice('elec', function(response){self.ready--;if(self.ready == 0) self.finishQuote();});
		this.updateServicePrice('water', function(response){self.ready--;if(self.ready == 0) self.finishQuote();});
		this.updateServicePrice('telephone', function(response){self.ready--;if(self.ready == 0) self.finishQuote();});
		this.updateServicePrice('broadband', function(response){self.ready--;if(self.ready == 0) self.finishQuote();});
		this.updateServicePrice('tv_license', function(response){self.ready--;if(self.ready == 0) self.finishQuote();});
		if(this.telephoneConnectionType != null && this.service['telephone']){
			this.updateConnectionCharge(function(response){self.ready--;if(self.ready == 0) self.finishQuote();});
		}else{
			this.ready--;
			if(this.ready == 0) this.finishQuote();
		}
		if(this.broadbandActivationCharge != null && this.service['broadband']){
			this.updateBroadbandActivationCharge(function(response){self.ready--;if(self.ready == 0) self.finishQuote();});
		}else{
			this.ready--;
			if(this.ready == 0) this.finishQuote();
		}
	}
	
	this.finishQuote = function(){
		if(this.waitingOnQuote){
			this.waitingOnQuote = false;
			this.recalculateQuote();
			return;
		}
		this.updateTotal();
		$(window).trigger('updateComplete');
		this.log('FINISHED UPDATING QUOTE');
	}
	
	this.updateConnectionCharge = function(callback){
		this.log('Getting quote for connection charge');
		if(this.telephoneConnectionType.type == 'transfer' || this.telephoneConnectionType.type == 'restart'){
			this.telephoneConnectioncharge = {notes: '', per_tenant: '00.00', total: '00.00'};
			$(window).trigger('telephoneConnectionCharge', {price: 0, total: 0});
			callback(this.telephoneConnectioncharge);
		}else{
			var self = this;
			$.ajax({
				type:	'POST',
				data:	{tenants: this.numberOfTenants, period: this.minTerm, ordertype: this.telephoneConnectionType.type, broadband: this.service['broadband']},
				url:	'/ajax/getConnectionChargeQuote/',
				dataType: 'json',
				success: function(jsonObject) {
					self.telephoneConnectioncharge = jsonObject;
					$(window).trigger('telephoneConnectionCharge', {price: jsonObject.per_tenant, total: jsonObject.total});
					callback(jsonObject);
				},
				error:	function() {
					error_dialog('Server error','We were unable to contact the server, please refresh the page and try again.');
				}
			});
		}
	}
	
	this.updateServicePrice = function(service, callback){
		if(!this.service[service]){
			callback(false);
			return true;
		}
		var self = this;
		var extra = '';
		if(service == 'elec'){
			if(!this.service['gas'] && this.greenEnergy) extra = 'green,nogas';
			else if(this.service['gas'] && this.greenEnergy) extra = 'green';
			else if(!this.service['gas'] && !this.greenEnergy) extra = 'nogas';
		}else if(service == 'broadband'){
			extra = this.broadbandOption;
		}else if(service == 'water'){
			extra = this.postcode;
		}
		this.log('Getting quote for service: '+service+'('+extra+')');
		$.ajax({
			type:	'POST',
			data:	{service: service, tenants: this.numberOfTenants, period: this.minTerm, extra: extra},
			url:	'/ajax/getServiceQuote/',
			dataType: 'json',
			success: function(json) {
				self.prices[service] = json;
				$(window).trigger('servicePriceUpdated', {service: service, price: json.tenant_week});
				callback(json);
			},
			error:	function() {
				error_dialog('Server error','We were unable to contact the server, please refresh the page and try again.');
			}
		});
	}
	
	this.updateTotal= function(){
		var self = this;
		var total = 0;

		$.each(this.prices, function(key, value){
			if(self.service[key]){
				total += parseFloat(value.tenant_week);
			}
		});
		$(window).trigger('totalPriceUpdated', {total: total.toFixed(2)});
	}
	
	this.getBroadbandActivationCharge = function(){
		var self = this;
		$.ajax({
			type:	'POST',
			data:	{mac: this.mac, minterm: this.minTerm},
			url:	'/ajax/getBroadbandActivationCharge/',
			dataType: 'json',
			success: function(json) {
				self.broadbandActivationCharge = json.price;
				self.updateBroadbandActivationCharge(function(){});
			},
			error:	function() {
				error_dialog('Server error','We were unable to contact the server, please refresh the page and try again.');
			}
		});
	}
	
	this.updateBroadbandActivationCharge = function(callback){
		var ppp = (this.broadbandActivationCharge /this.numberOfTenants).toFixed(2);
		$(window).trigger('broadbandActivationChargeUpdated', {price: ppp, total: this.broadbandActivationCharge});
		callback();
	}
	
	this.log = function(msg){
		if(this.verbose) console.log(msg)
	}
	
}
