function PxOnKeyUpDynamic(url, inputField, refControlNames, keyEvent, actionType) {
  if (url.length == 0)
    return;

  var e = window.event || keyEvent;
  if(e != null && e.keyCode !== undefined)
  {
      if (e.keyCode == 13)
        $(inputField).trigger('SelectValueChanged');

	  if (e.keyCode == 40 || e.keyCode == 38 || e.keyCode == 13)
		return;
   
	  if (e.keyCode == 17) { // ctrl key
		searchOptionCtrlOn = false;
		return;
	  }

	  if (searchOptionCtrlOn && e.keyCode != 86)
		return;
  }

  try {
	  var JSONstr = JSON.stringify({
		"PXMI3JSONAction": "FromUiItem",
		"ActionType": actionType,
		"UiItemId": inputField.id,
		"MainControlValue": inputField.value? inputField.value.trim() : '', //readonly input = no value element in DOM
		"RefControlValues": GetReferenceFilterValuesDynamic(inputField, refControlNames)
	  });
	  PxInvalidateItem(inputField.id);
	  PxAjaxPost(url, JSONstr);
  }
  catch(e) {
	  console.log("Aborting AJAX request: " + e);
  }
}


function GetReferenceFilterValuesDynamic(inputField, refControlNames) {
  var refControlValues = [];
  for (var refName in refControlNames) {
    var value = pxapp[refName];
    if (value === undefined || value === null) 
      throw ('Unexpected value for field ' + refName);
    var handlers = referenceFilterCustomRequestHandlers[inputField.id];
    if (handlers) {
        var customHandler = handlers[refName];
        if (customHandler)
            value = customHandler(value);
    }
    refControlValues.push(value);
  } 
  return refControlValues;
}

function PxOnSearchKeyUpDynamic(inputField, refControlNames, keyEvent) {
	//response is a getlist
	PxOnKeyUpDynamic(pxapp.ajaxUrl, inputField, refControlNames, keyEvent, "DoSearchFilter");
}

function PxOnTextInputKeyUpDynamic(inputField, refControlNames) {
	//textinput = response is a Get (can only physically display 1 record anyways)
	PxOnKeyUpDynamic(pxapp.ajaxUrl, inputField, refControlNames, null, "DoTextInputFilter");
}


function PxOnKeyUp(url, inputField, refControlNames, keyEvent, actionType) {
  if (url.length == 0)
    return;

  var e = window.event || keyEvent;
  if(e != null && e.keyCode !== undefined)
  {
	  if (e.keyCode == '40' || e.keyCode == '38' || e.keyCode == '13')
	  {
		if (e.keyCode == '13')
		  $(inputField).trigger('SelectValueChanged');
		return;
	  }
   
	  if (e.keyCode == 17) { // ctrl key
		searchOptionCtrlOn = false;
		return;
	  }

	  if (searchOptionCtrlOn && e.keyCode != 86)
		return;
  }
	//$(inputField).attr('data-is-valid', 0);
  try {
	  var JSONstr = JSON.stringify({
		"PXMI3JSONAction": "FromUiItem",
		"ActionType": actionType,
		"UiItemId": inputField.id,
		"MainControlValue": inputField.value? inputField.value.trim() : '', //readonly input = no value element in DOM
		"RefControlValues": GetReferenceFilterValues(inputField, refControlNames)
	  });
	  PxInvalidateItem(inputField.id);
	  PxAjaxPost(url, JSONstr);
  }
  catch(e) {
	  console.log("Aborting AJAX request: " + e);
  }
}

function PxOnSearchKeyUp(url, inputField, refControlNames, keyEvent) {
	//response is a getlist
	PxOnKeyUp(url, inputField, refControlNames, keyEvent, "DoSearchFilter");
}

function PxOnTextInputKeyUp(url, inputField, refControlNames) {
	//textinput = response is a Get (can only physically display 1 record anyways)
	PxOnKeyUp(url, inputField, refControlNames, null, "DoTextInputFilter");
}

$('.DpsDropList').on('change', function() { $(this).trigger('SelectValueChanged'); });
$('.DpsTextField').on('change', function() { $(this).trigger('SelectValueChanged'); }); //not tested, maybe keydown is needed...

function PxDoDroplistReferencing(url, triggeringRefControl, mainControl, refControlNames, jsEvent) {
  //note: this is triggered only by RELEVANT controls so there is no need to check triggeringRefControl.attr('name') at it will always be a relevant control.
  //no validation or anything, just chuck it in.
  var JSONstr = JSON.stringify({
    "PXMI3JSONAction": "FromUiItem",
    "ActionType": "DoDroplistFilter",
    "UiItemId": mainControl[0].id,
    "MainControlValue": mainControl[0].value,
    "RefControlValues":  GetReferenceFilterValues(mainControl[0], refControlNames)
  });
  PxInvalidateItem(mainControl[0].id);
  PxAjaxPost(url, JSONstr);
}

function PxInvalidateItem(UiItemId) {
  if($("#" + UiItemId)!==undefined)
    $("#" + UiItemId).attr('data-is-valid', 0);
}

function PxAjaxPost(uri, JSONstr) {
  XmlHttp = GetXmlHttpObject();
  if (XmlHttp == null)
      return;
  XmlHttp.onreadystatechange = PxOnXmlHttpObjectStateChanged;
  XmlHttp.requestText = JSONstr;
  XmlHttp.open("POST", uri);
  XmlHttp.send(JSONstr);
}


// Handles input for search. We need to handle up/down and return keys to make it easier to use the search results popup.
function PxOnSearchInputKeyDown(e) {
  var e = e || window.event;
  var divId = document.activeElement.id + '_' + "list";
  var existing = document.getElementById(divId);

  if (e.keyCode == 17) // ctrl key
    searchOptionCtrlOn = true;

  if (searchOptionCtrlOn && e.keyCode == 86) // v key
    searchOptionPasteOn = true;

  if (existing != null) {
    // up or down keys.
    if (e.keyCode == '40' || e.keyCode == '38') {
      var increment = 0;
      if (e.keyCode == '40') increment = 1; // down key.
      if (e.keyCode == '38') increment = -1; // up key.

      var length = existing.children != null ? existing.children.length : 0;
      if (length > 0 && increment != 0) {
        var currentlySelected = 0;
        for (var i = 0; i < length; ++i) {
          if (Number(existing.children[i].getAttribute('data-selected')) === 1) {
            // found the currently selected.
            existing.children[i].setAttribute('data-selected', 0);

            currentlySelected = (i + increment >= length) ? 0 : (i + increment); // check max
            currentlySelected = (currentlySelected < 0) ? (length - 1) : currentlySelected; // check min
            break; // ignore rest.
          }
        }

        if ($(existing.children[currentlySelected]).text() != searchOptionNoResultsFound) {
          existing.children[currentlySelected].setAttribute('data-selected', 1);
          return false;
        }
      }
    }

    if (e.keyCode == '13') {
      var currentElement = $(document.activeElement);

      // if we've got the search box open, select the highlighted
      var length = existing.children != null ? existing.children.length : 0;
      var currentValue = null;
      if (length > 0) {
        for (var i = 0; i < length; ++i) {
          if (Number(existing.children[i].getAttribute('data-selected')) === 1) {
            // found the currently selected. set and remove the search.
            currentValue = $(existing.children[i]).text();
            break;

          }
        }

        if (!currentValue) {
          currentValue = $(existing.children[0]).text();
        }

        if (currentValue != searchOptionNoResultsFound) {
          currentElement.val(currentValue);
          searchOptionMouseHighlighted = false; // reset so we can remove the current popup.
          currentElement.blur();
          currentElement.focus();
        } else {
          // show data invalid for 'Add' operation
          currentElement.attr('data-is-valid', 0);
        }
      }
      return false; //don't pass the event further up as that causes form submit (so stop event propogation + preventDefault)
    }

    // tab key.
    if (e.keyCode == '9')
      searchOptionMouseHighlighted = false; // reset so we can remove the current popup.
  }

  return PxCheckForAndHandleSubmission(e); //handle submission the same way as a textinput
}

function PxOnSearchInputPaste() {
  searchOptionPasteOn = true;
  var e = $.Event('keyup');
  e.which = 86;
  setTimeout(function() {
    $(this).trigger(e);
  }.bind(this), 0);
}

var referenceFilterCustomRequestHandlers =  {};

function GetReferenceFilterValues(inputField, refControlNames) {
  var refControlValues = [];
  for (var i = 0; i < refControlNames.length; ++i) {
    var refElements = $("[name=" + refControlNames[i] + "]:not(span)");
    if(refElements.length) {
		var refElement = refElements[0];
		var value = refElement.value;
		if(referenceFilterCustomRequestHandlers[inputField.id] != undefined) {
			var customHandler = referenceFilterCustomRequestHandlers[inputField.id][refElement.name];
			if(customHandler != undefined)
				value = customHandler(value);
		}
		refControlValues.push(value);
	}
    else
      refControlValues.push("");
  } 
  
  return refControlValues;
}
