# Source: generateSpectrumGraphs.js

    /**
     * Available functions in the file are
     *      {generateCorrespondingGraph}, {graphOnClickActions}
     * Generating multiple graphs with different scan Id.
     * 1.   Once the data is loaded from local files from the function {promiseLoadDataJS} from multiscan.js,
     *      it sets the data into global variables ms2_ScansWithData and ms1_ScansWithData.
     * 2.   Once the data is set to the global variables, then it creates navigation elements by calling
     *      {createMs1NavEements}, {createMs2NavEements}.
     * 3.   Once navigation elements are generated, {graphOnClickActions} function is called to set the
     *      on click actions on the navigation buttons of the spectrum graph
     */
    // function svgIds()
    // {
    //     this.ms2SvgId = "ms2svg_";
    //     this.ms2popUpSvgId = "ms2svg_popup_";
    //     return this;
    // }
    /**
     *
     * @param {Array} current_data - Contains a list with ion data if it is generating Mono Mass spectrum,
     * contians peaklist and enveloplist if generating spectrums of MS1/MS2
     * @param {String} id - Contains the id of spectrum svg with _ followed by scan number (monoMassSvg_872/ms2svg_870)
     * @param {Float} prec_mz - Contains the mass to which the graph needs to be zoomed
     * @param {Int} specId - Contains the spectrum number
     */
    function generateCorrespondingGraph(current_data,id,prec_mz,specId){
        // Gets the svg id of the spectrum
        let startOfId = id.split("_")[0];
        let graphFeatures = new GraphFeatures();
        if(startOfId == "monoMassSvg")
        {
            let calculatePrefixAndSuffixMassObj = new CalculatePrefixAndSuffixMass();
            let massShift_in = calculatePrefixAndSuffixMassObj.getIonTypeMass("B");
            let seq = calculatePrefixAndSuffixMassObj.getSequence(prsm_data);
            let massShiftList = calculatePrefixAndSuffixMassObj.getUnknownMassList();
            let prefixMassList = calculatePrefixAndSuffixMassObj.getPrefixMassList(seq,massShiftList,massShift_in);
            massShift_in = calculatePrefixAndSuffixMassObj.getIonTypeMass("Y");
            let suffixMassList = calculatePrefixAndSuffixMassObj.getSuffixMassList(seq,massShiftList,massShift_in);
            // Setting the graphFeatures object with all the features needed for the graph
            graphFeatures.showSequence = true;
            graphFeatures.addErrorPlot = true;
            graphFeatures.prefixSequenceData = prefixMassList;
            graphFeatures.suffixSequeceData = suffixMassList;
            graphFeatures.svgHeight = graphFeatures.svgHeight + graphFeatures.adjustableHeightVal + graphFeatures.heightForErrorPlot;
            graphFeatures.padding.head = graphFeatures.padding.head + graphFeatures.adjustableHeightVal;
            graphFeatures.padding.bottom = graphFeatures.padding.bottom + graphFeatures.heightForErrorPlot;
            graphFeatures.adjustableIonPosition = 10; // Random tested value for alignment
            // Gets the data list with mass error to plot in the monomass spectrum
            graphFeatures.errorListData = json2ErrorDataList(prsm_data.prsm);
            console.log(graphFeatures.errorListData);
            // Gets the absolute max and minimum value for upper bound and lower bound of y axis to draw the error plot
            graphFeatures.errorThreshHoldVal = getAbsoluteMaxValfromList(graphFeatures.errorListData);
            // Invoking spectrum function to draw the spectrum
            spectrumgraph = new addSpectrum(id, current_data, null, prec_mz, current_data,graphFeatures);
        }
        else{
            let peak_data = new PeakData();
            // Get the formatted peak data list
            let peak_list = peak_data.getPeakData(current_data);
            // Get formatted envelope data list
            let envelope_list = peak_data.getEnvelopeData(current_data);
            // Check if MS1 spectrum should be drawn
            if(id != "popupspectrum")
            {
                let ionData = peak_data.getIonData(prsm_data,specId,current_data);
                ms2_graph = new addSpectrum(id, peak_list, envelope_list, prec_mz, ionData, graphFeatures);
            }
            else{
                graphFeatures.isAddbgColor = true;
                // Get precursor mass to zoom to that point on launch of MS1 spectrum
                let precursor_mass = prsm_data.prsm.ms.ms_header.precursor_mono_mass;
                graphFeatures.bgMinMz = (graphFeatures.ratio * prec_mz) - graphFeatures.fixedWidthOfBgColorForMs1;
                graphFeatures.bgMaxMz = (graphFeatures.ratio * prec_mz) + graphFeatures.fixedWidthOfBgColorForMs1;
                spectrumgraph = new addSpectrum(id, peak_list, envelope_list, prec_mz, null,graphFeatures);
            }
        }
    }

    /**
     * Function to redraw the spectrum on popup window on click of download button for respected scan number
     * @param {Array} current_data - contains peak list and envelope list data of the corresponding spectrum(Scan Number)
     * @param {String} id - Contains the Id of the SVG tag to which the spectrum need to be drawn
     * @param {Object} spectrumParameters - Contains spectrum parameters to apply same to the pop window spectrum
     * @param {Int} specId - Contains the Spec Id of the corresponding graph
     */
    function reDrawWithSpecParams(current_data,id,spectrumParameters,specId)
    {
        let peak_data = new PeakData();
        let peak_list = peak_data.getPeakData(current_data);
        let envelope_list = peak_data.getEnvelopeData(current_data);
        let ionData = peak_data.getIonData(prsm_data,specId,current_data);
        peak_list.sort(function(x,y){
    		return d3.descending(x.intensity, y.intensity);
    	})
        envelope_list = sortEnvelopes(envelope_list) ;
        let svgId = "#"+id;
        let peakData = {peak_list:peak_list, envelope_list:envelope_list};
        let graphFeatures = new GraphFeatures();
        new SpectrumGraph(svgId,spectrumParameters,peakData, ionData,graphFeatures);
    }
    /**
     * This generates spectrum for each spec Id
     * @param {String} divId - Contains Id of the div tag under which the monomass graphs are drawn
     * @param {String} svgId - Contains id as "monoMassSvg_" to which scan Id is added
     * @param {String} className - Contains class name to which the corresponding svg graphs are drawn
     * @param {Array} data - contains the data of all the scans available
     */
    function createMultipleSvgs(divId,svgId,className,data){
        let div = document.getElementById(divId);
        data.forEach(function(element,i){
            let id = svgId+element.scanId;
            let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");;
            svg.setAttribute("id",id);
            svg.setAttribute("class",className);
            svg.style.backgroundColor = "#F8F8F8";
            if(i != 0)
            {
                svg.style.display = "none";
            }
            div.appendChild(svg);
            generateCorrespondingGraph(element.value,id,null,element.specId);
        });
    }

    /**
     * Function to hide graphs of all other spectrums other than current showing spectrum
     * @param {String} id - Contains Id of the SVG tag to be shown
     * @param {String} className - className of the spectrums to be hidden
     */
    function showCorrespondingGraph(id,className)
    {
        $(className).hide();
        document.getElementById(id).style = "block";
    }
    /**
     * Generating Jquery Onclick actions
     */
    function graphOnClickActions(){

        // On click of download button on the main page of the prsm
        $("#graph_download").click(function(){
            // Get the Scan number of the Current spectrum graph showing on the screen
            let currentGraphNode = $('.ms2_scanIds.active')[0].text;
            let scanId = currentGraphNode.split(" ")[1];
            // Get the data tot he correcponding Scan Id
    		let [current_data,specId] = getCurrentData(ms2_ScansWithData,scanId);
            let id = "ms2svg_"+scanId;
            // Get SpectrumParametes and copy to a new variable. This way of copying doesn't pass reference rather creates new copy
            // correspondingSpecParams_g is a global variable contians the spec parameters of each spectrum
            let specparams = jQuery.extend(true, {}, correspondingSpecParams_g[id]);
            let graphFeatures = new GraphFeatures();
            document.getElementsByName("show_envelops")[0].checked = graphFeatures.showCircles;
            document.getElementsByName("show_ions")[0].checked = graphFeatures.showIons;
            // Redraw the graph with correspondong specparameters
            reDrawWithSpecParams(current_data,"popup_ms2_spectrum",specparams,specId);
            // This allows pop up window to be moved
    		$("#ms2spectrumpop").draggable({
    			appendTo: "body"
    		});
        })

        // ms2_scanIds is the Id of the nav tabs for multiple navs.
        // On Click shows corresponding graph by hiding others.
    	$(".ms2_scanIds").click(function(){
            let value = this.getAttribute('value');
            let [currentData,specId] = getCurrentData(ms2_ScansWithData,value);
            id = "ms2svg_"+value;
            // Hide all the graphs except the one clicked
            showCorrespondingGraph(id,".ms2_svg_graph_class");
    		$("#ms2_graph_nav .active").removeClass("active");
       		$(this).addClass("active");
    	})

        // Hide all othe graphs of monomass spectrum other than the one clicked
        $(".monoMass_scanIds").click(function(){
    		let value = this.getAttribute('value');
            let [currentData,specId] = getCurrentData(monoMassDataList,value);
            id = "monoMassSvg_"+value;
            // Hide all the graphs except the one clicked
            showCorrespondingGraph(id,".monoMass_svg_graph_class");
    		$("#monoMass_nav .active").removeClass("active");
       		$(this).addClass("active");
        })

        // On click of mono mass mz, zoom all the graph to the corresponding point
        $(".peakRows").click(function() {
    		let parent_id  = $(this).parent().parent().prop('id');
    		let CurrentScanVal = document.getElementById(parent_id).firstChild.innerHTML;
    		/*	get Mono M/z value till 3 decimal values	*/
    		let peak_value = parseFloat(this.innerHTML).toFixed(3) ;
    		let [currentData,specId] = getCurrentData(ms2_ScansWithData,CurrentScanVal);
            let id = "ms2svg_"+CurrentScanVal;
            showCorrespondingGraph(id,".ms2_svg_graph_class");
            generateCorrespondingGraph(currentData,id,peak_value,specId);
            id = "monoMassSvg_"+CurrentScanVal;
            showCorrespondingGraph(id,".monoMass_svg_graph_class");
            [currentData,specId] = getCurrentData(monoMassDataList,CurrentScanVal);
            let CurrentMonoMassVal = $("#"+parent_id+" .row_monoMass").html();
            generateCorrespondingGraph(currentData,id,parseFloat(CurrentMonoMassVal),specId);
            activateCurrentnavbar("ms2_graph_nav",CurrentScanVal);
            activateCurrentnavbar("monoMass_nav",CurrentScanVal);

    		showSpectrun();
        });
        // By changing the graph features, on click of redraw invoke this and generate the pop spectrun repectively to be downloaded
        $("#ms2_popup_redraw").click(function(){
            let currentGraphNode = $('.ms2_scanIds.active')[0].text;
            let scanId = currentGraphNode.split(" ")[1];
    		let [current_data,specId] = getCurrentData(ms2_ScansWithData,scanId);
            let id = "popup_ms2_spectrum";
            // Copying as a new variable than referencing. Referencing will change the properties of parent if child properties are changes
            // However, this is a shallow copying, we need to do this for all needed objects in side specparams
            let specparams = jQuery.extend(true, {}, correspondingSpecParams_g[id]);
            specparams.graphFeatures = jQuery.extend(true, {}, correspondingSpecParams_g[id].graphFeatures);
            specparams.graphFeatures.showCircles = document.getElementsByName("show_envelops")[0].checked ;
            specparams.graphFeatures.showIons = document.getElementsByName("show_ions")[0].checked ;
            reDrawWithSpecParams(current_data,"popup_ms2_spectrum",specparams,specId);
        })

    }
    /**
     * Function return the absolute max error value from the list
     * @param {Array} errorDataList - Contains the list of mass errors
     */
    function getAbsoluteMaxValfromList(errorDataList){
        let max = 0;
        errorDataList.forEach((element,index)=>{
            let val = Math.abs(element.mass_error);
            if(max < val) max = val;
        })
        //Getting the round off fraction value
        max = max * 100;
        max = Math.ceil(max)/100;
        console.log("max : ", max);
        return max;
    }