
/**
 * Determine if dynamic HTML is supported.  In particular, ability to swap in innerHTML.
 * Not sure all of the nuances, but at least Internet Explorer and FireFox seem to work
 */
function dynamicHtmlSupported()
{
    var support = false;
    // navigator.appCodeName
    // navigator.appName
    // navigator.appVersion
    if ( navigator.userAgent.indexOf('MSIE') > -1 || navigator.userAgent.indexOf('Firefox') > -1 )
    {
        support = true;
    }
    return support;
}

/**
 * Add the selected SMILES string and respective HTML representation to the synthesis pathway frame
 *
 * smilesToHtmlMap: Associative array (i.e. map / dictionary) between SMILES strings and HTML representation
 * pathwayDoc: Document object for the pathway frame
 */
function addReactant( smiles, smilesToHtmlMap, pathwayDoc )
{
    if ( dynamicHtmlSupported() )
    {   // Looks like dynamic HTML supported.  Try copying over reactant depiction dynamically
        theForm = pathwayDoc.forms[0];

        // Copy to hidden form field to ensure data is persisted across page requests
        var openReactantField = theForm.reactant;
        if ( openReactantField.length )
        {   // Actually a list of multiple items.  Select the current / top one.
            openReactantField = theForm.reactant[0];
        }
        var openReactantPlaceholder = pathwayDoc.all.openReactant;

        var reactantSmilesArray = openReactantField.value.split( theForm.MOL_LIST_DELIM.value );
        if ( openReactantField.value == theForm.blankReactant.value )
        {   // Current contents is just a blank placeholder, clear it out
            reactantSmilesArray = Array();  // Ensure an empty array
            openReactantPlaceholder.innerHTML = '';
        }
        reactantSmilesArray.push( smiles ); // Add the new reactant
        openReactantField.value = reactantSmilesArray.join( theForm.MOL_LIST_DELIM.value );

        // Copy over the depiction
        var newReactantHtml = smilesToHtmlMap[smiles];
        if ( openReactantPlaceholder.innerHTML != '' )
        {
            openReactantPlaceholder.innerHTML += theForm.REACTANT_HTML_DELIM.value;
        }
        openReactantPlaceholder.innerHTML += newReactantHtml;

    }
    else
    {   // Looks like dynamic HTML not supported.  Just fall back on old style method requiring a server request
        theForm = pathwayDoc.forms[0];
        theForm.new_smiles.value = smiles;
        theForm.command.name = 'copyProduct';
        theForm.submit();
    }
}



// ======================== List Manipulation Functions for Setup Pages ==================== //

/**
 * If selecting a pre-constructed problem, auto-select the problem setup parameters
 * such as category selection and maximum steps.
 */
function problemSelect( reactionSynthesisIdField )
{
    var theForm = reactionSynthesisIdField.form;
    var reaction_synthesis_id = reactionSynthesisIdField.value;

    var maxSteps;
    var categorySet;
    var categoryOption;
    if ( reaction_synthesis_id != '' )
    {
        maxSteps = maxStepsBySynthesisId[reaction_synthesis_id];
        if ( maxSteps < 1 )
        {   // Placeholder problem, not yet ready for usage
            alert('This problem is not yet available.  Please check back later.');
            resetProblemSelect( theForm );
            return false;
        }

        if ( theForm['maxSteps'] )
        {
            theForm.maxSteps.value = maxSteps;
            theForm.maxSteps.disabled = true;
        }
        if ( theForm['numReactions'] )
        {
            theForm.numReactions.value = maxSteps;
            theForm.numReactions.disabled = true;
        }
        

        categorySet = categorySetsBySynthesisId[reaction_synthesis_id];

        // Reverse iteration so that will end up favoring highlighting of items near beginning of list
        for( var i=theForm.reactionCategorySelected.options.length-1; i > -1; i-- )
        {
            categoryOption = theForm.reactionCategorySelected.options[i];
            categoryOption.selected = ( categorySet[categoryOption.value] );    // If value exists in set, then category should be selected
        }
        theForm.reactionCategorySelected.disabled = true;
        
        // Allow for printer friendly display
        if ( theForm.elements['PrinterFriendlySynthesisProblem'] )
        {
            theForm.elements['PrinterFriendlySynthesisProblem'].disabled = false;
        }
    }
    else
    {   // Must be reverting to normal state.  Undo any control disabling
        for( var i=0; i < theForm.elements.length; i++ )
        {
            theForm.elements[i].disabled = false;
        }

        // However, disable printer friendly display from setup page if working on a random problem
        if ( theForm.elements['PrinterFriendlySynthesisProblem'] )
        {
            theForm.elements['PrinterFriendlySynthesisProblem'].disabled = true;
        }
    }
    return true;
}

/**
 * If change some problem generation parameters, cannot be selecting a specific problem,
 * must be trying to generate a random one.
 */
function resetProblemSelect( theForm )
{
    var confirmed = true; //window.confirm('This will reset any problem selections to "random."  Are you sure you wish to continue?')
    if ( confirmed )
    {
        if ( theForm.elements["reaction_synthesis_id"] )
        {
            theForm.reaction_synthesis_id.selectedIndex = 0;
        }
        if ( theForm.elements["reactionListId"] )
        {
            theForm.reactionListId.selectedIndex = 0;
        }

        // Reset any form elements to enabled status
        for( var i=0; i < theForm.elements.length; i++ )
        {
            theForm.elements[i].disabled = false;
        }
    }
    return confirmed;
}

/**
 * A user class has just been selected.  Update the list
 * of relevant synthesis problems respectively.
 * Copies of the items are placed in the page level
 * backupOptionsByKey associative , so that
 * they may be recovered dynamically.
 *
 * Expect a global (window) level associative array problemIdByClassId
 *  with the information needed.
 */
function updateUserClass( userClassField, reactionSynthesisField )
{
    var theForm = userClassField.form;

    // First ensure the backup list is populated
    if ( !window.backupOptionsByKey )
    {   window.backupOptionsByKey = Array();
    }
    
    // Unique ID based on form and element name
    backupKey = theForm.name +"."+ reactionSynthesisField.name;
    if ( !window.backupOptionsByKey[backupKey] )
    {
        window.backupOptionsByKey[backupKey] = Array();
        for( var i=0; i < reactionSynthesisField.options.length; i++ )
        {
            var nextOption = reactionSynthesisField.options[i];
            window.backupOptionsByKey[backupKey].push( nextOption );
        }
    }

    // Clear out the current contents of the list
    while( reactionSynthesisField.options.length > 0 )
    {
        reactionSynthesisField.remove(reactionSynthesisField.options.length-1);
    }
    
    // Now copy the options back in, but only those that fit the desired user class
    for( var i=0; i < window.backupOptionsByKey[backupKey].length; i++ )
    {
        var nextOption = window.backupOptionsByKey[backupKey][i];
        if ( synthesisOptionFitsClass( nextOption, userClassField ) )
        {
            reactionSynthesisField.options.add( nextOption );
        }
    }

    // Reset list to neutral state, since it has just been modified
    resetProblemSelect( theForm );
}

/**
 * Separate general function to decide whether a synthesis option
 * fits with the current user class field selection.
 */
function synthesisOptionFitsClass( synthesisOption, userClassField )
{
    var user_class_id = userClassField.value;
    var problemId = synthesisOption.value;
    if ( user_class_id.length < 1 || problemId.length < 1 )
    {   // Always accept the default selections (with a blank value)
        return true;
    }
    else
    {   // Check global / window level associative array for key information
        return ( window.problemIdsByClassId[user_class_id][problemId] );
    }
}

/**
 * User selected a specific textbook.  Filter down reaction 
 * subject categories (chapter list) to the relevant ones.
 * Copies of the items are placed in the page level
 * categoryOptionsBackupByForm dictionary (associative array), so that
 * they may be recovered dynamically.
 */
function textbookSelectChange( textbookSelectField, reactionCategoryField, synthesisSelectField )
{
    var theForm = textbookSelectField.form;

    // First ensure the backup list is populated
    if ( !window.categoryOptionsBackupByForm )
    {   // Associative array / dictionary
        window.categoryOptionsBackupByForm = Array();   
    }
    if ( !window.categoryOptionsBackupByForm[theForm.name] )
    {   // Separate backup per form, or else get inconsistencies when try to use both forms at the same time
        window.categoryOptionsBackupByForm[theForm.name] = Array(); 
        for( var i=0; i < reactionCategoryField.options.length; i++ )
        {
            var nextOption = reactionCategoryField.options[i];
            window.categoryOptionsBackupByForm[theForm.name].push( nextOption );
        }
    }

    // Clear out the current contents of the list
    while( reactionCategoryField.options.length > 0 )
    {
        reactionCategoryField.remove(reactionCategoryField.options.length-1);
    }
    
    // Now copy the options back in, but only those that fit the desired criteria
    for( var i=0; i < window.categoryOptionsBackupByForm[theForm.name].length; i++ )
    {
        var nextOption = window.categoryOptionsBackupByForm[theForm.name][i];
        if ( reactionCategoryOptionFitsClass( nextOption, textbookSelectField ) )
        {
            reactionCategoryField.options.add( nextOption );
        }
    }
    
    if ( synthesisSelectField )
    {   // Redo the problemSelect function to highlight relevant categories,
        //  since the above function may have rearrangedd the category list
        problemSelect( synthesisSelectField );
    }
}

/**
 * Separate general function to decide whether a reaction category option
 * fits with the current textbook field selection.
 */
function reactionCategoryOptionFitsClass( reactionCategoryOption, textbookSelectField )
{
    if ( textbookSelectField.value.length < 1 || reactionCategoryOption.value.length < 1 )
    {   // Always accept the default selections (with a blank value)
        return true;
    }
    else
    {   // Categories should start with a prefix matching the textbook
        return ( reactionCategoryOption.text.indexOf(textbookSelectField.value) == 0 );
    }
}

// Be ready to store backup of reaction subject category list
var categoryOptionsBackupByForm = null;
