/* define 'global' (i.e., persistent) variables */
var currentSelection = '';


/* GetSelectedText *************************************************************
 Activated by 'onMouseUp' event in the 'PDBsequence' div.
 Detects the location of a text selection in the PDBsequence div (actually in
 the entire document), relative to a static base point.  The selection location
 is translated into a numerical range like '113-145', with the help of the
 dynamic js function AdjustSelectionOffsetAccordingToProteinAlignment.
 This range is then sent to jmolAccent for highlighting.
*******************************************************************************/
function GetSelectedText() {
    var start;
    var end;
    var string;
    if ( window.getSelection ) {                             // mozilla browsers
        var selectionObject = window.getSelection();
        var rangeObject = getRangeObject( selectionObject ); // Safari quirk
        start = rangeObject.startOffset+1;
        end   = rangeObject.endOffset;

        str = selectionObject;

    }
    else if ( document.selection && document.selection.createRange ) { // IE
        var selectionObject = document.selection;
        var rangeObject = selectionObject.createRange();

        // I'm going to use a bookmark object to get the selection position.
        // The bookmark object stores current position of the insertion point,
        //  but with respect to the document string, not the element string.
        // So we need to set a base location...
        var baseLocationText = '#offset base#';
        var baseLocationOffset = baseLocationText.length + 1;
        var docRangeObject = document.body.createTextRange();
        if ( !docRangeObject.findText( baseLocationText ) ) {
            alert( "could not find " + baseLocationText );
        }
        else {
            docBookmark = docRangeObject.getBookmark();
            refStart = docBookmark.charCodeAt(2) - 1 - docBookmark.charCodeAt(0);
        }
        var selectionLength = rangeObject.text.length;
        bookmark = rangeObject.getBookmark();
        start = bookmark.charCodeAt(2) - 1 - bookmark.charCodeAt(0)
              - ( refStart + baseLocationOffset );
        end   = start + selectionLength - 1;

        str = rangeObject.text;

    }
    else {
        str = "Sorry, this is not possible with your browser.";
    }

    // account for various idiosynchracies in the pdb file numbering
    start = AdjustSelectionOffsetAccordingToProteinAlignment( start );
    end   = AdjustSelectionOffsetAccordingToProteinAlignment(  end  );

    // highlight residues corresponding to selection in Jmol window
//    alert ( "calling jmolAccent with positions " + start + "-" + end );
    if ( start && end ) {       // don't accent if either is undefined
        if ( start < end ) {    // handles clicking instead of selecting
            jmolAccent( start + "-" + end, 0 );
        }
        else {
            jmolAccent( end + "-" + start, 0 );
        }
    }
}

/* This function is only needed to account for some Safari weirdness */
function getRangeObject( selectionObject ) {
    if ( selectionObject.getRangeAt )              // most mozilla browsers
        return selectionObject.getRangeAt( 0 );
    else {                                         // Safari!
        var rangeObject = document.createRange();
        rangeObject.setStart( selectionObject.anchorNode,selectionObject.anchorOffset );
        rangeObject.setEnd( selectionObject.focusNode,selectionObject.focusOffset );
        return rangeObject;
    }
}

/* jmolAccent ******************************************************************
 Takes a string like '230-242, 315' as an argument, and highlights the indicated
 residues in the Jmol display.  An optional second argument set to 'true' will
 leave any previously highlighted residues 'on' - the default is to erase any
 previous highlighting. Queries the 'multiple selections persist' and 'high-
 contrast highlighting' checkbox states and acts accordingly. Also prints the
 currently highlighted sequence numbers into 'currently highlighted' text box.

 jmolAccent is now called by the 'select display style' and 'pick color scheme'
 selection menus also - actually they call the jmolRender... functions, which
 send the contents of 'currently highlighted' to jmolAccent as the residueList.
*******************************************************************************/
function jmolAccent( residueList, distance, chain, persist ) {

    // kludge in case residueList is empty,
    // e.g. when jmolAccent is called by one of the style selection menus
    if( residueList == '' ) { residueList = 'none'; }
    // (because 'select ;' seems to be equivalent to 'select all;' instead)

    /* detect 'persist' and 'contrast' checkbox states */
    var contrast = false;
    if( document.jmolForm.contrast.checked == true ) { contrast = true; }
    // 'persist' may have a value initialized by argument
    if( document.jmolForm.persist.checked  == true ) { persist  = true; }

    /* declare variables */
    var colorSchemeScript = '';
    var displayStyleScript = '';
    var accentColorFor = { 'white'            : 'red',
                           'dodgerblue'       : 'red',
                           'group'            : 'deeppink',
                           'amino'            : 'deeppink',
                           'temperature'      : 'yellow',
                           'cpk'              : 'cyan',
                           'structure'        : 'cyan',
                           'shapely'          : 'cyan',
                           'property_entropy' : 'deeppink',
                         };
    var chain = document.jmolForm.mainChain.value;
    var currentAccentedResidues = document.jmolForm.showPDBcoords.value;

    /* get states and scripts for current look */
    currentColorScheme        = ( document.jmolForm.colorScheme.value )
                              ?   document.jmolForm.colorScheme.value
                              :  'dodgerblue';
    currentDisplayStyle       = ( document.jmolForm.displayStyle.value )
                              ?   document.jmolForm.displayStyle.value
                              :  'default';
    currentDisplayStyleScript = jmolDisplayStyleScriptFor( currentDisplayStyle );

    /* style and color the background molecule(s) first */
    if( contrast ) {
        colorSchemeScript = 'select all; color translucent white; '
    }
    else {
        colorSchemeScript = 'select :' + chain + ' and not ligand; color ' + currentColorScheme;
    }
    resetStyleScript = "select all; wireframe off; spacefill off; cartoon off;\
                        ribbon off; rocket off; strand off; trace off; halos off; ";
    displayStyleScript = resetStyleScript + currentDisplayStyleScript;
//    alert( 'whole molecule style script: ' + displayStyleScript );
    jmolScriptWait( displayStyleScript );
//    alert( 'whole molecule color scheme script: ' + colorSchemeScript );
    jmolScriptWait( colorSchemeScript );

    /* accent the selected residues after molecule style & color is set */

    // Be ready to prepend 'near chain ' to the 'Currently highlighted' text,
    //  if the residue list is just a chain identifier.
    var near = ( residueList && residueList != 'none' && !residueList.match( /\d/ ) )
        ? 'near chain '
        : '';
    var selected = '';

//    alert( "Before changes...\ncurrentAccentedResidues: " + currentAccentedResidues + "\n                        residueList: " + residueList );
    var selectResidueList = ''; // this will be the select script for highlighting
    if( currentAccentedResidues == residueList ) {
        // If the residue lists are identical, this should just be a change of
        //  display style or color scheme - so use the stored selection set.
        // Restore the previous selection first:
        jmolScriptWait('select none; restore SELECTION "highlighted";');
        selectResidueList = "select selected; ";
    }
    else {     // Otherwise, there are new residues to be highlighted.
        var persistingResidues = '';
        if( persist ) {
            // Restore the previous selection:
            jmolScriptWait('select none; restore SELECTION "highlighted";');
            selected = 'selected, ';
            // Append new residues in residueList argument to the 'Currently highlighted' list
            //  (unless it is empty).
            persistingResidues = currentAccentedResidues + ', ';
        }
        currentAccentedResidues = persistingResidues + near + residueList;

        // Modify the provided residue list - add chain information, etc. - for the select script
        if( residueList.match( /\d/ ) ) { // residueList is a residue set
            residueList = residueList.replace( /,/, ':'+chain+',' ) + ':' + chain;
        }
        else {                  // residueList is a chain identifier
            residueList = ':' + residueList.replace( /,/, ':,' );
        }
        selectResidueList
            = "select " + selected // this part keeps previously highlighted stuff, if 'persist'
            + "within( " + distance + ", 'false', " + residueList + " ) and :"
            + chain + "; ";
    }
//    alert( "current accented residues (for 'Currently highlighted' box):\n[" + currentAccentedResidues + "]" );
//    alert( "selectResidueList (Jmol select script):\n[" + selectResidueList + "]" );

    displayStyleScript = selectResidueList;
//    alert( 'currentDisplayStyle is ' + currentDisplayStyle );
    var saveSelectScript = ' save SELECTION "highlighted";';
    if( currentDisplayStyle != 'ballAndStick' && currentDisplayStyle != 'wireframe' ) {
        displayStyleScript += currentDisplayStyle;
        colorSchemeScript
            = selectResidueList
            + saveSelectScript
            + ' color ' + accentColorFor[ currentColorScheme ] + '; ';
    }
    else if( contrast && currentColorScheme != 'default' ) {
        colorSchemeScript = selectResidueList
                          + saveSelectScript
                          + ' color halos ' + currentColorScheme + ';'
                          + ' halos on; ';
    }
    else {
        colorSchemeScript = selectResidueList
                          + saveSelectScript
                          + ' color halos ' + accentColorFor[ currentColorScheme ] + ';'
                          + ' halos on; ';
    }

    /* update the 'Currently highlighted' textbox */
    document.jmolForm.showPDBcoords.value = currentAccentedResidues;

//    alert( 'accent style script: ' + displayStyleScript );
    jmolScriptWait( displayStyleScript );
//    alert( 'accent color scheme script: ' + colorSchemeScript );
    jmolScriptWait( colorSchemeScript + 'select all' );

}

function jmolHighlightResiduesNearLigand( ligand_chain, distance, main_chain ) {

    var script = 'select within( '
        + distance
        + ', false, :'
        + ligand_chain
        + ') and :'
        + main_chain
        + '; color red; select :'
        + ligand_chain
        + '; color limegreen; select not( :'
        + ligand_chain + ', :' + main_chain
        + '); color yellow';
//    alert( script );
    jmolScriptWait( script );

}

/* used by the 'select display style' select menu on pssv.html page */
function jmolRenderDisplayStyle( styleChoice ) {
    if ( !styleChoice ) { return; }
    highlightedResidues = document.jmolForm.showPDBcoords.value;
    jmolAccent( highlightedResidues, 0 );
}

function jmolDisplayStyleScriptFor( styleChoice ) {
    if ( styleChoice == 'default' )      { return "cartoon; " };
    if ( styleChoice == 'ballAndStick' ) { return "wireframe 20; spacefill 25%; " };
    if ( styleChoice == 'spacefill' )    { return "spacefill; " };
    if ( styleChoice == 'wireframe' )    { return "wireframe 50; " };
    if ( styleChoice == 'ribbons' )      { return "ribbon; " };
    if ( styleChoice == 'cartoon' )      { return "cartoon; " };
    if ( styleChoice == 'rockets' )      { return "rockets; " };
    if ( styleChoice == 'strand' )       { return "strand; " };
    if ( styleChoice == 'trace' )        { return "trace; " };
    if ( !styleChoice )                  { return "" };
}

/* used by the 'pick color scheme' select menu on pssv.html page */
function jmolRenderColorScheme( colorChoice ) {
    if ( !colorChoice ) { return; }
    highlightedResidues = document.jmolForm.showPDBcoords.value;
    jmolAccent( highlightedResidues, 0 );
}

function jmolColorSchemeScriptFor( colorChoice ) {
    if ( colorChoice == 'default' )     { return "color dodgerblue; " };
    if ( colorChoice == 'cpk' )         { return "color cpk; " };
    if ( colorChoice == 'structure' )   { return "color structure; " };
    if ( colorChoice == 'group' )       { return "color group; " };
    if ( colorChoice == 'temperature' ) { return "color temperature; " };
    if ( colorChoice == 'amino' )       { return "color amino; " };
    if ( colorChoice == 'shapely' )     { return "color shapely; " };
    if ( colorChoice == 'entropy' )     { return "color entropy; " };
    if ( !colorChoice )                 { return "" };
}

function disableSelection( target ) {
    if ( typeof target.onselectstart != "undefined" ) //IE route
        target.onselectstart = function() { return false }
    else if ( typeof target.style.MozUserSelect != "undefined" ) //Firefox route
                target.style.MozUserSelect = "none"
    else //All other routes (ie: Opera)
        target.onmousedown = function() { return false }
            target.style.cursor = "default"
}
