/**
  * Ext.ux.data.PagingMemoryProxy.js
  *
  * A proxy for local / in-browser data structures
  * supports paging / sorting / filtering / etc
  *
  * @file	Ext.ux.PagingMemoryProxy.js
  * @author	Ing. Ido Sebastiaan Bas van Oostveen
  * 
  * @changelog:
  * @version    1.3
  * @date       30-September-2007
  *             - added customFilter config option
  * @version	1.2 
  * @date	29-September-2007
  *		- fixed several sorting bugs
  * @version	1.1
  * @date	30-August-2007
  * @version	1.0
  * @date	22-August-2007
  *
  */

Ext.namespace("Ext.ux");
Ext.namespace("Ext.ux.data");

/* Fix for Opera, which does not seem to include the map function on Array's */
if(!Array.prototype.map){
    Array.prototype.map = function(fun){
	var len = this.length;
	if(typeof fun != "function"){
	    throw new TypeError();
	}
	var res = new Array(len);
	var thisp = arguments[1];
	for(var i = 0; i < len; i++){
	    if(i in this){
		res[i] = fun.call(thisp, this[i], i, this);
	    }
	}
        return res;
     };
}

/* Paging Memory Proxy, allows to use paging grid with in memory dataset */
Ext.ux.data.PagingMemoryProxy = function(data, config) {
	Ext.ux.data.PagingMemoryProxy.superclass.constructor.call(this);
	this.data = data;
	Ext.apply(this, config);
};

Ext.extend(Ext.ux.data.PagingMemoryProxy, Ext.data.MemoryProxy, {
	customFilter: null,
	
	load : function(params, reader, callback, scope, arg) {
		params = params || {};
		var result;
		try {
			result = reader.readRecords(this.data);
		} catch(e) {
			this.fireEvent("loadexception", this, arg, null, e);
			callback.call(scope, null, arg, false);
			return;
		}
		
		// filtering
		if (this.customFilter!=null) {
			result.records = result.records.filter(this.customFilter);
			result.totalRecords = result.records.length;
		} else if (params.filter!==undefined) {
			result.records = result.records.filter(function(el){
			    if (typeof(el)=="object"){
					var att = params.filterCol || 0;
					return String(el.data[att]).match(params.filter)?true:false;
			    } else {
					return String(el).match(params.filter)?true:false;
			    }
			});
			result.totalRecords = result.records.length;
		}
		
		// sorting
		if (params.sort!==undefined) {
		    // use integer as params.sort to specify column, since arrays are not named
		    // params.sort=0; would also match a array without columns
		    var dir = String(params.dir).toUpperCase() == "DESC" ? -1 : 1;
        	    var fn = function(r1, r2){
			    return r1==r2 ? 0 : r1<r2 ? -1 : 1;
        	    };
		    var st = reader.recordType.getField(params.sort).sortType;
		    result.records.sort(function(a, b) {
				var v = 0;
				if (typeof(a)=="object"){
				    v = fn(st(a.data[params.sort]), st(b.data[params.sort])) * dir;
				} else {
				    v = fn(a, b) * dir;
				}
				if (v==0) {
				    v = (a.index < b.index ? -1 : 1);
				}
				return v;
		    });
		}

		// paging (use undefined cause start can also be 0 (thus false))
		if (params.start!==undefined && params.limit!==undefined) {
			result.records = result.records.slice(params.start, params.start+params.limit);
		}
		
		callback.call(scope, result, arg, true);
	}
});




/* AJAXPro Data Proxy Classes */
Ext.data.AjaxProxy = function(ajaxProObject, method) {
	Ext.data.AjaxProxy.superclass.constructor.call(this);
	this.ajaxProObject = ajaxProObject;
	this.method = method;
};
Ext.extend(Ext.data.AjaxProxy, Ext.data.DataProxy, {
	load: function(params, reader, callback, scope, arg) {
		if(this.fireEvent("beforeload", this, params) !== false) {
			var s = [];
			for (var x in params) {
				s[s.length] = "params[\"" + x + "\"]";
			}
			s = s.join(",");
			var o = {
				params: params || {},
				request: {
					callback : callback,
					scope : scope,
					arg : arg
				},
				reader: reader,
				callback: this.loadResponse,
				scope: this
			};
			eval("this.ajaxProObject[this.method](" + s + ", this.loadResponse, o)");
		} else {
			callback.call(scope||this, null, arg, false);
		}
	},
	loadResponse: function(response, request) {
		var o = response.context;
		var self = o.scope;
		if(!!response.error) {
			alert('response error: '+response.error.Message);
			self.fireEvent("loadexception", self, o, response.error);
			o.request.callback.call(o.request.scope, null, o.request.arg, false);
			return;
		}
		var result;
		var json = {responseText: response.json.substring(0, response.json.length - 3)};
		//alert(response.json);
		try {
			result = o.reader.read(json);
		} catch(e) {
			self.fireEvent("loadexception", self, o, json, e);
			o.request.callback.call(o.request.scope, null, o.request.arg, false);
			return;
		}
		o.request.callback.call(o.request.scope, result, o.request.arg, true);
	}
});
if(typeof AjaxPro != "undefined" && AjaxPro !== null){ 
    AjaxPro.timeoutPeriod = 60000; 
    AjaxPro.onTimeout = function(b,res){ 
            alert('Timeout'); 
    } 
    AjaxPro.onLoading = function(b){ 
            //Do nothing for now 
    } 
    AjaxPro.onError = function(res){ 
            alert('error:'+res.Message); 
    }
}








/* This is the primary Layout */
MLS = function(){

    var layout;
    var rds,ds,contentPanel,previewBody,pagingToolbar;
    var propertyPreview;    
    var innerLayout;
    var lv;
    var lm;
    var selBeds,selBaths,selMinPrice,selMaxPrice,selSqFt,selZip;
    var pageSize;

    
    MLS.superclass.constructor.call(this); 
    this.init();
    return this;
};

Ext.extend(MLS,Ext.Component, {


    
	init : function(){
	
	    this.pageSize=20;
	
	
	    //Create Combos by transform:
	    selBeds=new Ext.form.ComboBox({
	        id:'selBeds',
            typeAhead: false,
            triggerAction: 'all',
            transform:'sel_beds',
            width:115,
            forceSelection:true
        });
        selBaths=new Ext.form.ComboBox({
            id:'selBaths',
            typeAhead: false,
            triggerAction: 'all',
            transform:'sel_baths',
            width:115,
            forceSelection:true
        });
        selMinPrice=new Ext.form.ComboBox({
            id:'selMinPrice',
            typeAhead: false,
            triggerAction: 'all',
            transform:'sel_min_price',
            width:115,
            forceSelection:true
        });
        selMaxPrice=new Ext.form.ComboBox({
            id:'selMaxPrice',
            typeAhead: false,
            triggerAction: 'all',
            transform:'sel_max_price',
            width:115,
            forceSelection:true
        });
        selSqFt=new Ext.form.ComboBox({
            id:'selSqFt',
            typeAhead: false,
            triggerAction: 'all',
            transform:'sel_sqft',
            width:115,
            forceSelection:true
        });
        selZip=new Ext.form.ComboBox({
            id:'selZip',
            typeAhead: false,
            triggerAction: 'all',
            transform:'sel_zip',
            width:115,
            forceSelection:true
        });

		layout = new Ext.BorderLayout('MLSContainer', {
		    west: {
			    split:true,
			    initialSize: 220,
			    minSize: 220,
			    maxSize: 350,
			    titlebar: true,
			    collapsible: true,
			    animate: true,
			    autoScroll:true,
			    animate:true
			    //cmargins: {top:0,bottom:0,right:0,left:0}
		    },
		    center: {
			    split:false,			    
			    tabPosition: 'top',
			    closeOnTab: true,
			    //alwaysShowTabs: true,
			    resizeTabs: true,
			    autoScroll:true
			    //maxSize: 400
			    //initialSize: '100%'
		    }
		});
		
		layout.on('resize',this.resize(),this)
		Ext.EventManager.onWindowResize(this.resize,this);


		layout.beginUpdate();
		layout.add('west', new Ext.ContentPanel('ListingsSearchOptions', {title:'Search Options',fitToFrame:true}));
		
		//layout.add('south', new Ext.ContentPanel('footer_container',{fitToFrame:true}));



		
		//Add Listing Toolbar:
		var tb = new Ext.Toolbar('ListingsToolbar');
		tb.add('Sort:');
		tb.add('-');
        tb.add(new Ext.Toolbar.Button({id:'btnSortPrice',field:'list_price',dir:'DESC',text:'Price',handler:this.sort,cls:'x-btn-text-icon',icon:strModulePath+'images/icons/sort_desc.gif'}));
        tb.add('-');
        tb.add(new Ext.Toolbar.Button({id:'btnSortSqft',field:'square_feet',dir:'ASC',text:'Sq Ft',handler:this.sort,cls:'x-btn-text-icon',icon:strModulePath+'images/icons/1x1.gif'}));
        tb.add('-');
        tb.add(new Ext.Toolbar.Button({id:'btnSortBeds',field:'beds',dir:'ASC',text:'Beds',handler:this.sort,cls:'x-btn-text-icon',icon:strModulePath+'images/icons/1x1.gif'}));
        tb.add('-');
        tb.add(new Ext.Toolbar.Button({id:'btnSortBaths',field:'baths',dir:'ASC',text:'Baths',handler:this.sort,cls:'x-btn-text-icon',icon:strModulePath+'images/icons/1x1.gif'}));
		
		//lv = layout.add('center', new Ext.ContentPanel('ListingsViewContainer',{fitToFrame:true,autoScroll:true}));
		//this.createView(lv.getEl());
		
		
		
		// the inner layout houses the sort toolbar and the listing viewpanel
		var innerLayout = new Ext.BorderLayout('main', {
		north: {
			split:false,
			autoScroll:false,
			alwaysShowTabs:false,
			collapsible:false,
			titlebar:false,
			minHeight:27,
			initialSize:27	
		},
		center: {
		    split:false,			    
		    tabPosition: 'top',
		    closeOnTab: true,
		    resizeTabs: true,
		    autoScroll:true,
		    alwaysShowTabs:false
		},
		south: {
			split:false,
			autoScroll:false,
			alwaysShowTabs:false,
			collapsible:false,
			titlebar:false,
			minHeight:27,
			initialSize:27	
		}
		});
		// add the nested layout
		contentPanel = new Ext.NestedLayoutPanel(innerLayout, 'Property List');
		layout.add('center', contentPanel);

		innerLayout.beginUpdate();
        var ListContainer = new Ext.ContentPanel('ListingsViewContainer', {fitToFrame:true,autoScroll:true});
		lv = innerLayout.add('center',ListContainer );
		
		this.createView(lv.getEl());
		
		innerLayout.add('north', new Ext.ContentPanel('toolbar_container',{title:'Sort Options',fitToFrame:true}));
		//viewFooter=new Ext.ContentPanel('paging_container',{title:'',fitToFrame:true});
		innerLayout.add('south', new Ext.ContentPanel('paging_container',{title:'',fitToFrame:true}));

		// restore innerLayout state
		innerLayout.restoreState();
		innerLayout.endUpdate(true);
		
		var mapPanel=new Ext.ContentPanel('MapContainer', 
		    {fitToFrame:true,
		    fitContainer:true,
		    useShim:true,
		    resizeEl:'main',
		    autoScroll:false,
		    title:'Property Locator'}
		);
		mapPanel.on('activate',this.activateMap,mapPanel);
		layout.add('center',mapPanel)
        layout.getRegion('center').showPanel(contentPanel)
		// restore any state information
		//initializeGMap();
		layout.monitorWindowResize=true;
		layout.restoreState();
		layout.endUpdate();
		
		//initializeGMap();
		
		this.loadFeed('');
		layout.layout();


            
	},
	
	activateMap : function(mapPanel) {
	    //Draw the points on Map...
        var drawDelay=0;
        center_map=true; //sets global, so first good geoCoder centers map.
        ds.each(function(rec){
            var loc=rec.get('address')+','+rec.get('city')+' OK'
            var content=
              '<div class="feed-item-'+getFeaturedClass(rec.get('featured_listing'))+'" valign="top" style="width:325px;">' +
              '<table border="0" cellspacing="4">' +
              //'<tr><td valign="top" colspan="3"><div class="listing-header-'+getFeaturedClass(rec.get('featured_listing'))+'"></div></td></tr>' +
              '<tr><td valign="top" colspan="3"><img src="' + strModulePath + 'images/listing-header-'+getFeaturedClass(rec.get('featured_listing'))+'.gif"></td></tr>' +
              '<tr><td valign="top" align="left" width="150"><img style="border: 1px solid #666666;" src="' + 
              strModulePath + 'mlsthumb.aspx?mls=' + rec.get('mlsnum') + '&h=113&w=150&path=' + strModulePath + 'mls_images/" ' + 
              'width="150px" height="113px" onerror="this.src=\'' + strModulePath + 'images/no_image.jpg\';">' +
              '<div class="list-price">'+Ext.util.Format.usMoney(rec.get('list_price'))+'</div>' +              
              '<td valign="top"><div class="item-title">'+rec.get('address')+', '+rec.get('city')+' '+rec.get('zipcode')+'</div>' +
              '<div class="item-title">'+rec.get('beds')+' bedrooms, '+rec.get('baths')+' bathrooms, '+rec.get('square_feet')+' sqft</div><br/>' +
              '<input class="x-form-item" type="button" value="More Details" onclick="ShowListing('+rec.get('mlsnum')+',\''+rec.get('hash')+'\');" /></td><td>&nbsp</td>' +               
              //'<div class="feed-desc">'+rec.get('public_remarks')+'</div></td>' +
              '</tr></table></div>'
            //alert(loc);
            drawDelay=drawDelay+250
            setTimeout(function(){showLocation(loc,content)},drawDelay);
        });
	    		        
	},
	
	sort : function(btn){
	    //alert('Sorted by price:'+but.text);
	    Ext.get('btnSortPrice').child('button:first').dom.style.backgroundImage = 'url('+strModulePath+'images/icons/1x1.gif)';
	    Ext.get('btnSortSqft').child('button:first').dom.style.backgroundImage = 'url('+strModulePath+'images/icons/1x1.gif)';
	    Ext.get('btnSortBeds').child('button:first').dom.style.backgroundImage = 'url('+strModulePath+'images/icons/1x1.gif)';
	    Ext.get('btnSortBaths').child('button:first').dom.style.backgroundImage = 'url('+strModulePath+'images/icons/1x1.gif)';
	    var newdir='ASC';
	    if(btn.dir=='ASC'){newdir='DESC'};
	    btn.dir=newdir;
	    btn.cls='sort-'+newdir.toString().toLowerCase()+' x-btn-text-icon';
	    btn.el.child('button:first').dom.style.backgroundImage = 'url('+strModulePath+'images/icons/sort_'+newdir+'.gif)';
	    ds.sort(btn.field,newdir);
	},

	resize : function () {
	    //alert('clientWidth:' + Ext.get('body').dom.clientWidth);
	    //alert('x:' + this.getWindowXY().x);
	    var win;
	    win=this.getWindowXY();
	    
	    
	    Ext.get('ModuleWrapper').dom.style.width=win.x-165;        
        Ext.get('ModuleWrapper').dom.style.height=win.y-265;
        Ext.get('MapContainer').dom.style.width=win.x-165;        
        Ext.get('MapContainer').dom.style.height=win.y-265;
	    layout.layout();
	},
	
	getWindowXY : function() {
        
        var o = new Object();
        o.x = 0;
        o.y = 0;
        if( typeof( window.innerWidth ) == 'number' ) {
        //Non-IE
        o.x = window.innerWidth;
        o.y = window.innerHeight;
        } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
        //IE 6+ in 'standards compliant mode'
        o.x = document.documentElement.clientWidth;
        o.y = document.documentElement.clientHeight;
        } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
        //IE 4 compatible
        o.x = document.body.clientWidth;
        o.y = document.body.clientHeight;
        }
        //window.alert( 'Width = ' + myWidth );
        //window.alert( 'Height = ' + myHeight );
        return o;
        
	},
        
    createView : function(el){
        function reformatDate(feedDate){
            var d = new Date(Date.parse(feedDate));
            return d ? d.dateFormat('D M j, Y, g:i a') : '';
        }
        

        
        /* */
        /* Ext / AjaxPro Data Reader */
        /* */
         
        var reader = new Ext.data.JsonReader({id: 'mlsnum', root:'records',totalProperty:'count'},
            ['mlsnum','address', 'list_price','city','zipcode','public_remarks','square_feet','baths','beds','featured_listing','hash']);

//      rds=SWIRL.MLS.AJAX.SearchListings(0,0,0,999999,0,0,1927,0,25).value
        // create the Data Store
//        ds = new Ext.data.Store({
//	        proxy: new Ext.ux.data.PagingMemoryProxy(rds),
//	        reader : reader,
//            remoteSort: true
//        });
    
        ds = new Ext.data.Store({
            proxy: new Ext.data.AjaxProxy(SWIRL.MLS.AJAX, "SearchListings"),
            reader : reader,
            remoteSort: false,
            remotePaging: true
        });
        ds.baseParams={beds:0,baths:0,min_price:0,max_price:999999,sqft:0,zipcode:0,office:sel_office};
        
        
        ds.on('load', this.onLoad, this);
        
        //lm = new Ext.LoadMask(el, {store:ds}); 
        
        var tpl = new Ext.Template(
              '<div class="feed-item-{featured}" valign="top">' +
              '<table border="0" cellspacing="4" width="100%">' +
              //'<tr><td valign="top" colspan="3"><div class="listing-header-{featured}" /></td></tr>' +
              '<tr><td valign="top" colspan="3"><img src="' + strModulePath + 'images/listing-header-{featured}.gif"></td></tr>' +
              '<tr><td valign="top" align="left" width="150"><img style="border: 1px solid #666666;" src="' + 
              strModulePath + 'mlsthumb.aspx?mls={mls}&h=113&w=150&path=' + strModulePath + 'mls_images/" ' + 
              'width="150px" height="113px" onerror="this.src=\'' + strModulePath + 'images/no_image.jpg\';">' +
              '<div class="list-price">{price}</div>' +
              '<input class="x-form-item" type="button" value="More Details" onclick="ShowListing({mls},\'{hash}\');" /></td><td>&nbsp</td>' +               
              '<td valign="top" align="left"><div class="item-title">{address}, {city} {zipcode}</div>' +
              '<div class="item-title">{beds} bedrooms, {baths} bathrooms, {square_feet} sqft</div><br/>' +
              '<div class="feed-desc">{desc}</div></td>' +
              '</tr></table></div>'
        );
        //var dtlbtn=new Ext.Button('btn_details',{text:'Details'})
        //tpl.append(dtlbtn);
        
        var view = new Ext.View(el, tpl, {
            store: ds,
            loadingText:'Loading...',
            singleSelect:true, 
            selectedClass:'selected-article', 
            jsonRoot : 'records'
        });
        view.prepareData = function(data){
            return {
	            mls: data.mlsnum,
                title: data.address,
                price: Ext.util.Format.usMoney(data.list_price),
                featured: getFeaturedClass(data.featured_listing),
                desc: data.public_remarks.replace(/<\/?[^>]+>/gi, '').ellipse(350),
                beds: data.beds,
                baths: data.baths,
                address: data.address,
                city: data.city,
                zipcode: data.zipcode,
                square_feet: data.square_feet,
                hash: data.hash
            
            };
        };
        //var viewFooter = Ext.get(view.el.dom.parentNode).createChild({tag: "div", cls:"viewFooter"});
        var viewFooter = Ext.get('PagingToolbar')
        this.pagingToolbar = new Ext.PagingToolbar(viewFooter, ds, {
				pageSize: this.pageSize,
				displayInfo: true,
				//displayMsg:  "&copy; 2008 Tenkiller Lake Realty, LLC",
				emptyMsg: "bar"
			});
        
        /* Hang On, This will be done in due time. :) */
        view.on('click', this.showListing, this);
        //this.loadFeed();
    },
    
    onLoad : function(){
	    lv.getEl().scroll("top");
	    clearMap();
	    //alert(ds.getTotalCount());

    },
    
    loadFeed : function(feed){

        //alert('getting ready to load feed');
        //ds.load({params: {start:0,limit:25,beds:0,baths:0,min_price:0,max_price:999999,sqft:0,zipcode:0,office:1927}});  
        ds.load({params: {start:0,limit:this.pageSize}});  
        
    },
    
    showListing : function(view, dataIndex){            
	    var node = ds.getAt(dataIndex);
	    var mlsnum = node.data.mls;
	    var link = 'http://www.tenkillerlakerealty.com/CurrentListings/Residential/200000to299999/MLSListing705331/tabid/70/Default.aspx';
	    var desc = node.data.desc;

	    currentItem = {
	    index: dataIndex, link: link
	    };
	    
    },
    
    showInWindow : function(){
        if(currentItem){
            window.open(currentItem.link, 'win');
        }
    },
    
    search : function() {
        
       
        var sel_min_price=selMinPrice.getValue();
        var sel_max_price=selMaxPrice.getValue();
        var sel_sqft=selSqFt.getValue();
        var sel_zip=selZip.getValue();
        var sel_beds=selBeds.getValue();
        var sel_baths=selBaths.getValue();
        if (sel_zip==''){sel_zip='0'}
        
        ds.baseParams.beds=sel_beds;
        ds.baseParams.baths=sel_baths;
        ds.baseParams.min_price=sel_min_price;
        ds.baseParams.max_price=sel_max_price;
        ds.baseParams.sqft=sel_sqft;
        ds.baseParams.zipcode=sel_zip;
        
        
        layout.getRegion('center').showPanel(layout.getRegion('center').getPanel(0));
        clearMap();
        layout.width='800px';
        //ds.load({params: {beds:sel_beds,baths:sel_baths,min_price:sel_min_price,max_price:sel_max_price,sqft:sel_sqft,zipcode:sel_zip,office:sel_office,start:0,limit:25}});
        //ds.load({params: {start:0,limit:25,beds:sel_beds,baths:sel_baths,min_price:sel_min_price,max_price:sel_max_price,sqft:sel_sqft,zipcode:sel_zip,office:sel_office}});
        ds.load({params: {start:0,limit:this.pageSize}});
	
    }
});	


function ShowListing(mlsnum,hash){
    //window.open(strModulePath+'Listing.aspx?mls='+mlsnum+'&h='+hash);
    window.open('/Listing.aspx?mls='+mlsnum+'&h='+hash);
}	

Ext.onReady(
    function(){	   
        
        setTimeout(function(){Listings = new MLS()},2500);	    
	    setTimeout(function(){initializeGMap()},3000);
	    setTimeout('hideLoadMask()',3100);
	    
	}	
);

function hideLoadMask() {
    
    var mask = Ext.get('loading-mask');
    if(mask){
        var loading = Ext.get('loading');
        mask.setOpacity(.8);
        mask.shift({
              xy:loading.getXY(),
              width:loading.getWidth(),
              height:loading.getHeight(), 
              remove:true,
              duration:.5,
              opacity:.3,
              easing:'bounceOut',
              callback : function(){
                  loading.fadeOut({duration:.2,remove:true});
              }
        });
        document.getElementById('ListingsSearchOptions').style.visibility='visible';
    }
}


String.prototype.ellipse = function(maxLength){
    if(this.length > maxLength){
        return this.substr(0, maxLength-3) + '...';
    }
    return this;
};

function getFeaturedClass(featured){
    if(featured){
        return 'featured';
    } else {
        return 'normal';
    }
}

