﻿/*override FormLayout renderItem so it removes item + container*/
Ext.override(Ext.layout.FormLayout, {
    renderItem : function(c, position, target){
        if(c && !c.rendered && c.isFormField && c.inputType != 'hidden'){
            var args = [
                   c.id, c.fieldLabel,
                   c.labelStyle||this.labelStyle||'',
                   this.elementStyle||'',
                   typeof c.labelSeparator == 'undefined' ? this.labelSeparator : c.labelSeparator,
                   (c.itemCls||this.container.itemCls||'') + (c.hideLabel ? ' x-hide-label' : ''),
                   c.clearCls || 'x-form-clear-left' 
            ];
            if(typeof position == 'number'){
                position = target.dom.childNodes[position] || null;
            }
            if(position){
                c.formItem = this.fieldTpl.insertBefore(position, args, true);
            }else{
                c.formItem = this.fieldTpl.append(target, args, true);
            }
            c.render('x-form-el-'+c.id);
            c.container = c.formItem; // must set after render, because render sets it.
            c.actionMode = 'container';
        }else {
            Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
        }
    }
});




Ext.namespace('Ext.Mapper');


/*
* @class Ext.Mapper.SearchForm
* @extends Ext.form.FormPanel
*
* Author Mapper Search Form
*/
Ext.Mapper.SearchForm = Ext.extend(Ext.FormPanel, {
		
	initComponent : function() {
		
		Ext.apply(this, {
			labelAlign: 'top',
 			frame: false,
			border: false,
			width: 230,
			expanded : false,
			defaults : { labelSeparator: '' },
			items: [
				{
					xtype:'textfield',
					hideLabel : true,
					emptyText : 'Type search here',
					id: 'form-search',
					allowBlank:true,
					width:210
				},
				new Ext.Mapper.MultiFieldSet({
					id: 'form-fs-authors', 
					title: 'Authors', 
					trigger1Mode: 'hidden',
					indexName : 'meta:Author'
				}),
				new Ext.Mapper.MultiFieldSet({
					id: 'form-fs-subjects', 
					title: 'Subjects', 
					trigger1Mode: 'search',
					indexName : 'meta:Subject'
				}),
				new Ext.Mapper.MultiFieldSet({
					id: 'form-fs-orgs', 
					title: 'Institutions', 
					trigger1Mode: 'search',
					indexName : 'meta:OrgName'
				}),
				new Ext.Mapper.MultiFieldSet({
					id: 'form-fs-publications', 
					title: 'Publications', 
					trigger1Mode: 'search',
					indexName : 'meta:Publication'
				}),				
				new Ext.Mapper.MultiFieldSet({
					id: 'form-fs-countries', 
					title: 'Countries', 
					trigger1Mode: 'select',
					indexName : 'meta:Country'
				}),
				new Ext.Mapper.MultiFieldSet({
					id: 'form-fs-publishers', 
					title: 'Publishers', 
					trigger1Mode: 'select',
					indexName : 'meta:PubName'
				}),
				{
					xtype:'fieldset',
					id : 'form-fs-dates',
					title: 'Publish Date',
					autoHeight:true,
					items: {
						layout: 'column',
						border: false,
						items:[{
								columnWidth:.52,
								layout: 'form',
								border : false,
								items: new Ext.form.DateField({
									fieldLabel : 'From',
									labelSeparator: '',
									format : 'm/d/Y',
									id : 'form-from',
									width : 99
								})
						},{
								columnWidth:.48,
								layout: 'form',
								align: 'right',
								border: false,
								items: new Ext.form.DateField({
									fieldLabel : 'To',
									labelSeparator: '',
									format : 'm/d/Y',
									id : 'form-to',
									width : 99
								})
						}]
					}
			},
			{
				xtype: 'checkbox',
				id: 'form-openaccess',
				itemCls: 'openAccess',
				boxLabel: 'Open Access articles only'
			}
			],
			buttonAlign : 'right',
			buttons: [{
				id : 'btnSearch',
				text: 'Map it',
				handler : function() {
					/*build a search url from the form fields*/
					var url = "search.aspx?";
									
					var qs = Ext.getCmp("form-fs-countries").getValues("val=country:").concat(
						Ext.getCmp("form-fs-subjects").getValues("phr=subject:"),
						Ext.getCmp("form-fs-authors").getValues("phr=name:"),
						Ext.getCmp("form-fs-orgs").getValues("phr=orgname:"),
						Ext.getCmp("form-fs-publications").getValues("phr=publication:"),
						Ext.getCmp("form-fs-publishers").getValues("val=pubname:")
					);
									
					var search = Ext.getCmp("form-search");
					var searchValue = search.getValue().trim();
					if (searchValue && searchValue != search.emptyText) qs.push("q=" + encodeURIComponent(searchValue));
					
					var dateqs = "{0}-year={1}&{0}-month={2}&{0}-day={3}";
					
					var from = Ext.get("form-from").getValue();
					if (from.length == 10) {
						var dFrom = new Date(from);
						qs.push(String.format(dateqs, "start", dFrom.getFullYear(), dFrom.getMonth()+1, dFrom.getDate()));
					}
					
					var to = Ext.get("form-to").getValue();
					if (to.length == 10) {
						var dTo = new Date(to);
						qs.push(String.format(dateqs, "end", dTo.getFullYear(), dTo.getMonth()+1, dTo.getDate()));
					}
					
					if (Ext.getCmp('form-openaccess').getValue()) {
						qs.push('oa=1');
					}
						
					self.location = url + qs.join("&");
				} 
			}]
		});		
		Ext.Mapper.SearchForm.superclass.initComponent.call(this, arguments);
	},
	
	onRender : function(ct, position){
    this.initFields();
    Ext.FormPanel.superclass.onRender.call(this, ct, position);
    var o = {
        tag: 'div',
        id : this.formId || Ext.id()
    };
    this.form.initEl(this.body.createChild(o));
    
    var td = Ext.get('btnSearch').parent();
    td.set({'valign': 'top'});
    
    Ext.DomHelper.insertBefore(td,   
			{
				tag : 'td', 
				children : [
					{
						tag : 'a',
						id : 'search-toggleDisplay',
						href : 'javascript:;',
						onclick : 'Ext.getCmp(\'searchForm\').toggleDisplay(this);',
						html : 'Show all options'
					}
				]
			}
		);

  },
  
  toggleDisplay : function(a) { 
		if (!this.expanded) {
			this.items.each(function(i){ 
				if (i.show) i.show(); 
			});
			Ext.get(a).update('Hide unused options');
		}
		else {
			this.items.each(function(i){ 
				if (i.xtype === 'multifieldset' && i.isEmpty()) {
					i.hide();
				}
				if (Ext.get('form-from').getValue() === '' && Ext.get('form-to').getValue() === '') {
					Ext.getCmp('form-fs-dates').hide();
				}
				if (!Ext.getCmp('form-openaccess').getValue()) {
					Ext.getCmp('form-openaccess').hide();
				}
			});
			Ext.get(a).update('Show all options');
		}
		this.expanded = !this.expanded;
		try { a.blur(); } catch(e){}
  }
});



/*
* @class Ext.Mapper.AutoCompleteComboBox
* @extends Ext.form.ComboBox
*
* ComboBox configured for auto complete and match highlighting
*
* @constructor accepts config object:
*		id
*		store: Store for fields to use
*		trigger1Mode: "hidden" | "select" | "search"
*/
Ext.Mapper.AutoCompleteComboBox = Ext.extend(Ext.form.ComboBox, {
	
	trigger1Mode : 'hidden',
	
	initComponent : function() {
		Ext.apply(this, {
			hideLabel: true,
      mode: 'remote',
      displayField: 'name',
      valueField: 'name',
      emptyText:'',    
      forceSelection: false,        
      hideTrigger1: (this.trigger1Mode == 'hidden'),
      triggerAction: 'all',
      minChars: 3,
      trigger1Class : 'x-form-' + this.trigger1Mode + '-trigger',
      trigger2Class : 'x-form-clear-trigger',
      editable: true,
      maxHeight:200,
      width:208,
      listWidth : 350,
      tpl : new Ext.XTemplate('<tpl for="."><div class="x-combo-list-item">{[this.high(values.name)]} ({count})</div></tpl>',	{
				ownerId : this.id,
				high : function(str) { 
					return str.replace(new RegExp('('+ Ext.fly(this.ownerId).getValue() + ')','i'), '<em>$1</em>'); 
				}
			})
		});
		
		Ext.Mapper.AutoCompleteComboBox.superclass.initComponent.apply(this, arguments);		

	},
	initEvents : function(){
      Ext.form.ComboBox.superclass.initEvents.call(this);

      this.keyNav = new Ext.KeyNav(this.el, {
          "up" : function(e){
              this.inKeyMode = true;
              this.selectPrev();
          },

          "down" : function(e){
              if(!this.isExpanded()){
                  this.onTriggerClick();
              }else{
                  this.inKeyMode = true;
                  this.selectNext();
              }
          },

          "enter" : function(e){
              if (this.inKeyMode) {
								this.onViewClick();
								this.delayedCheck = true;
								this.unsetDelayCheck.defer(10, this);
							}
							else {
								this.collapse();
							}
							Ext.getCmp('btnSearch').handler();
							
          },

          "esc" : function(e){
              this.collapse();
          },

          "tab" : function(e){
              this.onViewClick(false);
              return true;
          },

          scope : this,

          doRelay : function(foo, bar, hname){
              if(hname == 'down' || this.scope.isExpanded()){
                 return Ext.KeyNav.prototype.doRelay.apply(this, arguments);
              }
              return true;
          },

          forceKeyDown : true
      });

      this.queryDelay = Math.max(this.queryDelay || 10,
              this.mode == 'local' ? 10 : 250);
      this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
      if(this.typeAhead){
          this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
      }
      if(this.editable !== false){
          this.el.on("keyup", this.onKeyUp, this);
      }
      if(this.forceSelection){
          this.on('blur', this.doForce, this);
      }
  },

	onTrigger1Click : function() {
		if (this.trigger1Class == 'x-form-search-trigger') {
			var browseWin = new Ext.Mapper.BrowseWindow({
				id : this.id + '-win',
				title : this.ownerCt.title,
				target : this
			});
			browseWin.load(this.getValue().substring(0,1));
		}
		else {
			this.onTriggerClick();
		}
	},
	
	onTrigger2Click : function() {
		this.destroy();
		this.ownerCt.itemCounter;
		//Commented to handle counter series of removed text box from facet.  
		//this.ownerCt.itemCounter--;
	},
	
	select : function(index, scrollIntoView){
    this.selectedIndex = index;
    this.view.select(index);
    
    var newVal = this.store.getAt(index).data[this.displayField];
    this.setValue(newVal);
    
    if(scrollIntoView !== false){
        var el = this.view.getNode(index);
        if(el){
            this.innerList.scrollChildIntoView(el, false);
        }
    }
	},
	
	onLoad : function(){
        if(!this.hasFocus){
            return;
        }
        if(this.store.getCount() > 0){
            this.expand();
            this.restrictHeight();
            if(this.lastQuery == this.allQuery){
                if(this.editable){
                    this.el.dom.select();
                }
                if(!this.selectByValue(this.value, true)){
                    //this.select(0, true);
                }
            }else{
                //this.selectNext();
                if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
                    this.taTask.delay(this.typeAheadDelay);
                }
            }
        }else{
            this.onEmptyResults();
        }
        //this.el.focus();
    }
  
});



/*
* @class Ext.Mapper.MultiFieldSet
* @extends Ext.form.Fieldset
*
* Extension to FieldSet that adds a store and abilty to add items dynamically
*
* @constructor takes config object:
*		id: Id of fieldset
*		title: Title of fieldset
*		store: Store for fields to use
*		trigger1Mode: "hidden" | "select" | "search"
*/
Ext.Mapper.MultiFieldSet = Ext.extend(Ext.form.FieldSet, {

    initComponent: function() {
        Ext.apply(this, {
            xtype: 'multifieldset',
            itemCounter: 0,
            autoHeight: true,
            store: new Ext.Mapper.FilterStore(this.indexName)
        });
        Ext.Mapper.MultiFieldSet.superclass.initComponent.apply(this, arguments);

        this.on('keyup', function(o, e) {
            console.log("key ", Ext.EventObject.getKey());
        });
    },

    addComboBox: function(renderForm, value) {
        var o = new Ext.Mapper.AutoCompleteComboBox({
            id: this.id + ++this.itemCounter,
            store: this.store,
            trigger1Mode: this.trigger1Mode,
            indexName: this.indexName
        });

        if (value) o.setValue(value);
        this.add(o);
        if (renderForm) this.ownerCt.render();
    },

    onRender: function(ct, position) {
        if (!this.el) {
            this.el = document.createElement('fieldset');
            this.el.id = this.id;
            this.el.appendChild(document.createElement('legend')).className = 'x-fieldset-header multi-fieldset';
        }

        Ext.form.FieldSet.superclass.onRender.call(this, ct, position);
		if(this.id != "form-fs-publications" && this.id != "form-fs-publishers")
		{
			var add = '<a href="#" onclick="Ext.getCmp(\'' + this.id + '\').addComboBox(true); this.blur(); return false;"><img src="/images/add.png" title="Add"></a>';
			Ext.DomHelper.append(this.header, add);
		}
    },

    getValues: function(qsPrepend) {
        if (!qsPrepend) qsPrepend = "";
        var values = [];
        for (var i = 1; i <= this.itemCounter; i++) {
            try {
                var val = Ext.fly(this.id + i).getValue();
                if (val != "") values.push(qsPrepend + encodeURIComponent(val));
            } catch (e) { }
        }
        return values;
    },

    getDescription: function() {
        var vals = this.getValues();
				for (var i=0; i<vals.length; i++) {
					vals[i] = decodeURIComponent(vals[i]);
				}
        return (vals.length > 0) ? this.title + ': ' + vals.join(',') : null;
    },

    isEmpty: function() {
        return this.getValues().length === 0;
    }

});


/*
* @class Ext.Mapper.BrowseWindow
* @extends Ext.Window
*
* Extension to Window that loads a list of facet terms
* (currently only journal but designed to be reusable if required)
*
* @constructor accepts config object
*/
Ext.Mapper.BrowseWindow = Ext.extend(Ext.Window, {
	
	id : 'browseWindow',
	layout : 'fit',
	maximizable : false,
	width : 530,
	height : 400,
	autoScroll : false,
	closable : true,
	closeAction : 'close',
	modal : true,
	plain : true,
	html : '<div id="browseWindowContent"><p class="loading-indicator">Loading...</p></div>',

	load : function(letter) {
		letter = letter || 'A';
		this.show();
		Ext.fly('browseWindowContent').update('<p class="loading-indicator">Loading...</p>');
		Ext.Ajax.request({
			url: String.format('/xqueries/facetbrowser.xqy?f={0}&letter={1}&id={2}', this.target.indexName, letter, this.id),
			disableCaching : true,
			success: function(r) {
				try {
					//need try/catch because window could have been closed before loaded
					Ext.fly('browseWindowContent').update(r.responseText);
					console.log(arguments);
				}
				catch(e) {}
			},
			failure: function(r) { 
				try {
					//need try/catch because window could have been closed before loaded
					Ext.fly('browseWindowContent').update('<p>Unavailable</p>');
				}
				catch(e) {}
			},
			scope: this
		});	
	},

	select : function(value) {
		this.target.setValue(value);
		this.close();
		return false;
	}

});


/*
* @class Ext.Mapper.FilterStore
* Wrapper round Ext.Data.Store to customize for combo-box filters
* @indexName: MarkLogic element range index
*/
Ext.Mapper.FilterStore = function(indexName) {
	return new Ext.data.Store({
				proxy: new Ext.data.HttpProxy(
					new Ext.data.Connection({
						url: '/xqueries/filter.xqy',
						disableCaching : false,
						extraParams : {f : indexName },
						method : 'GET'
				})), 
				reader: new Ext.data.XmlReader({record : 'item'}, Ext.data.Record.create([{name: 'name'},{name : 'count'}]))                 
	});
};

