jOmnis.callbackObject = {
    fieldData: null, // Field data is an object that stores the IDs, Tables, and Descriptions of fields in a list of search fields
    fields: null,
    findDiv: null,
    parentDiv: null,
    categoryList: null,
    fieldInput: null,
    clearButton: null,
    fieldList: null,
    //selectedFieldDisplay: null,
    enterKey: null,
    upKey: null,
    downKey: null,
    leftKey: null,
    rightKey: null,
    tabKey: null,
    shiftKey: null,
    navKeys: null,
    showAll: null,
    totalWidth: null,
    addCategories: function(){
        let categories = Object.keys(this.fieldData);
        categories.forEach(element => {
            let category = document.createElement("option");
            category.value = element;
            category.text = element;
            this.categoryList.add(category);
        });
        if(categories.length < 11){
            this.categoryList.classList.add('hidden-scroll');
            //The next two lines fix a strange behavior on MacOS that does not correctly apply the class above. They may be able to be deleted once the interface is in use.
            this.categoryList.size = '9';
            this.categoryList.size = '10';
        }
    },
    prepareFields: function(category){
        if(category == "All"){
            this.showAll = true;
            for (var category in this.fieldData) {
                this.fieldData[category].forEach(element => {
                    element.category = category;
                    this.fields.push(element);
                })
            }
        } else {
            this.showAll = false;
            this.fieldData[category].forEach(element => {
                this.fields.push(element);
            })
        }
        this.fields.sort(function(a,b){
            if (a.description > b.description){
                return 1;
            } else if (a.description < b.description){
                return -1;
            } else {
                if (a.category > b.category){
                    return 1;
                } else if (a.category < b.category){
                    return -1;
                } else {
                    return 0;
                }
            }
        });
        this.addFields(this.fields);
    },
    addFields: function(fieldsToAdd){
        this.fieldList.classList.remove('hidden-scroll');
        let fieldNames = fieldsToAdd.map(field => field.description);
        let numberOfFields = fieldsToAdd.length;
        fieldsToAdd.forEach((element, index) => {
            if(fieldNames.indexOf(element.description) != fieldNames.lastIndexOf(element.description)){
                element.duplicate = true;
            };
            let field = document.createElement("option");
            field.value = element.colname;
            field.id = element.omnisLine;
            field.text = element.description + (element.duplicate && this.showAll ? ` (${element.category})` : '');
            this.fieldList.add(field);
            if(index == 0){
                field.selected = true;
            }
        });
        if (numberOfFields == 0 && this.fieldInput.value){
            let field = document.createElement("option");
            field.value = "No Results";
            field.text = "No Results";
            field.disabled = true;
            this.fieldList.add(field);
        }
        if(numberOfFields < 11){
            this.fieldList.classList.add('hidden-scroll');
        }
    },
    filterFields: function(searchInput){
        let searchTerm = searchInput.toLowerCase();
        let filteredFields = this.fields.filter(element => {
                return element['description'].toLowerCase().includes(searchTerm)
        });
        this.clearFields();
        this.addFields(filteredFields);
    },
    handleClearBtn: function(key){
        let value = jOmnis.callbackObject.fieldInput.value;
        let result;
        if(key == "Backspace"){
            if(value){
            result = value.slice(0,-1);
            }
        } else {
            result = value + key  //have to handle the result this way since we are using keydown instead of keyup
        }
        if (result) {
            this.clearButton.style.visibility = 'visible';
        } else {
            this.clearButton.style.visibility = 'hidden';
        }
    },
    setWidths: function(){
        let categoryWidth = this.categoryList.offsetWidth;
        let fieldWidth = this.fieldList.offsetWidth - 5;
        let findDivWidth = this.findDiv.offsetWidth;
        let parentDivWidth = this.parentDiv.offsetWidth;
        let remainingWidth = parentDivWidth - categoryWidth - 26;
        this.totalWidth = categoryWidth + fieldWidth;
        this.fieldInput.style = `width: ${this.totalWidth}px`;
        if (findDivWidth >= parentDivWidth - 5){
            this.fieldList.style = `width: ${remainingWidth}px;`;
        } else {
            this.fieldList.style = `min-width: ${fieldWidth}px`;
        }
    },
    resetFieldsArray: function(){
        this.fields = [];
    },
    clearFields: function(){
        while(this.fieldList.firstChild) {
            this.fieldList.removeChild(this.fieldList.firstChild);
        }
    },
    clearInput: function(){
        this.fieldInput.value = '';
        this.clearButton.style.visibility = 'hidden';
        this.filterFields(this.fieldInput.value);
    },
    submitFieldChoice: function(){
        //These lines were included for testing purposes. They should be OK to delete once the interface is in use. 
        //let selectedColname = document.querySelector('#fields-list').value;
        //let selectedOmnisLine = document.querySelector(`option[value='${selectedColname}']`).id;
        //this.selectedFieldDisplay.textContent = `Colname: ${selectedColname} || Omnis Line: ${selectedOmnisLine} || Total Width: ${this.totalWidth}`;
        jOmnis.sendClickEvent(this.omnisGetCurrentLine()); // This causes the browser to run evClick in $event and passes it a line number
    },
    // Required for "single"! This needs to be updated to return the currently selected field's OmnisLine Property (see line 179)
    omnisGetCurrentLine: function() {
        let selectedOmnisLine = document.querySelector(`option[value='${selectedColname}']`).id;
        selectedOmnisLine = Number(selectedOmnisLine);
        return selectedOmnisLine;
    },
    runDemo: function() {
        this.addCategories();
        this.prepareFields("All");
        this.setWidths();
        //window.addEventListener('resize', this.setWidths);
        this.fieldInput.focus();
    },
    // Required!
    omnisOnLoad: function() {
        this.fieldData = {};
        this.fields = []
        this.findDiv = document.getElementById('find-div');
        this.parentDiv = document.getElementById('parent-div');
        this.categoryList = document.getElementById('field-categories');
        this.fieldInput = document.getElementById('field-input');
        this.clearButton = document.getElementById('clear-btn');
        this.fieldList = document.getElementById('fields-list');
        //this.selectedFieldDisplay = document.getElementById('selected-field');
        this.enterKey = 13;
        this.upKey = 38;
        this.downKey = 40;
        this.leftKey = 37;
        this.rightKey = 39;
        this.tabKey = 9;
        this.shiftKey = 16;
        this.navKeys = [this.enterKey, this.upKey, this.downKey, this.leftKey, this.rightKey, this.tabKey, this.shiftKey];
        this.fieldInput.focus();
    },
    // Required!
    omnisSetData: function(fieldData) {
        this.fieldData = {};
        this.fields = [];
        if (fieldData instanceof omnis_list) {
            for (var i = 0; i < fieldData.getRowCount(); i++) {
                // Check to see if the current table has been added to the field data object
                if (!(fieldData.getData(1, i + 1) in this.fieldData)) { // getData(column #, row #) it's important to note the omnis lists have a starting index of 1 which is why we do i + 1 in javascript
                    this.fieldData[fieldData.getData(1, i + 1)] = [];
                }

                this.fieldData[fieldData.getData(1, i + 1)].push({
                    "id": fieldData.getData(2, i + 1),
                    "description": fieldData.getData(3, i + 1),
                    "omnisLine": i + 1,
                    "colname": fieldData.getData(4, i + 1)
                });
                
            }
            
            //Typing in input updates field list
            this.fieldInput.addEventListener('keydown', function(e){
                let keycode = e.keyCode;
                let key = e.key;
                let value = e.target.value;
                
                if (jOmnis.callbackObject.navKeys.includes(keycode)){
                    return;
                } else {
                    let result;
                    if(key == "Backspace"){
                        if(value){
                        result = value.slice(0,-1);
                        }
                    } else {
                        result = value + key
                    }
                    jOmnis.callbackObject.filterFields(result);
                    jOmnis.callbackObject.handleClearBtn(key);
                    //jOmnis.callbackObject.setWidths();
                    jOmnis.callbackObject.submitFieldChoice();
                }
            });

            //Changing the category updates field list
            this.categoryList.addEventListener('change', function(e){
                let selectedCategory = e.target.value;
                jOmnis.callbackObject.clearFields();
                jOmnis.callbackObject.resetFieldsArray();
                jOmnis.callbackObject.fieldInput.value = '';
                jOmnis.callbackObject.prepareFields(selectedCategory);
                jOmnis.callbackObject.fieldInput.placeholder = `Search ${selectedCategory} Fields`
            });

            // Right arrow moves from category list to field list
            this.categoryList.addEventListener('keydown', function(e){
                if(e.keyCode == jOmnis.callbackObject.rightKey){
                    //document.querySelector('#fields-list option').selected = true;
                    jOmnis.callbackObject.fieldList.focus();
                }
            })

            //Clicking on a field gets the field ID
            this.fieldList.addEventListener('change', function(){
                jOmnis.callbackObject.submitFieldChoice();
            });

            //Enter key also gets the field ID
            this.fieldList.addEventListener('keydown', function(e){
                let keycode = e.keyCode;
                if (keycode == jOmnis.callbackObject.enterKey){
                    jOmnis.callbackObject.submitFieldChoice();
                } else if (keycode == jOmnis.callbackObject.leftKey){
                    jOmnis.callbackObject.categoryList.focus();
                }
            });

            //Most keys will bring focus to search input
            window.addEventListener('keydown', function(e){
                let keycode = e.keyCode;
                if (jOmnis.callbackObject.navKeys.includes(keycode)){
                    return;
                } else {
                    jOmnis.callbackObject.fieldInput.focus();
                }
            });
            // Up arrow, Down arrow, and Enter keys control field list
            this.fieldInput.addEventListener('keydown', function(e){
                let keycode = e.keyCode;
                let allFields = document.querySelectorAll('#fields-list option');
                let length = allFields.length;
                if (keycode == jOmnis.callbackObject.downKey){
                    e.preventDefault();
                    for (let i=0; i<length; i++){
                        let current = allFields[i];
                        let next = allFields[i+1];
                        if(current.selected && i<length-1){
                            current.selected = false;
                            next.selected = true;
                            break;
                        }
                    };
                } else if (keycode == jOmnis.callbackObject.upKey){
                    e.preventDefault();
                    for (let i=length-1; i>=0; i--){
                        let current = allFields[i];
                        let prev = allFields[i-1];
                        if(current.selected && i>0){
                            current.selected = false;
                            prev.selected = true;
                            break;
                        }
                    };
                } else {
                    return;
                }
                jOmnis.callbackObject.submitFieldChoice();
            });
        }

        this.runDemo();
    }
};