<!-- https://www.createwithdata.com/chartjs-and-csv/ -->
<!-- https://towardsdatascience.com/4-ways-to-improve-your-plotly-graphs-517c75947f7e -->

<?php
$branch = 'dev';

function getsmth($branch){
    $url = "https://cmd.inp.nsk.su/~compton/gitlist/compton_tables/raw/".$branch."/tables/";
    $text = file_get_contents($url);
    $arrays = explode("\n", $text);
    $clean_arrs = array_filter($arrays, function($value){
	$temp_arr = explode('/', $value);
        return preg_match("/[A-Z]+[0-9]+\//", $value);
    });
    foreach($clean_arrs as &$val){
        $val = substr($val, 0, -1);
    }
    return $clean_arrs;
}

$availableSeasons = getsmth($branch);

$season = isset($_GET["season"])&&in_array($_GET["season"], $availableSeasons) ? $_GET["season"] : reset($availableSeasons);
$url = "https://cmd.inp.nsk.su/~compton/gitlist/compton_tables/raw/".$branch."/tables/".$season."/";
$url_total_info = "https://cmd.inp.nsk.su/~compton/gitlist/compton_tables/raw/".$branch."/tables/".$season.".csv";
$text = file_get_contents($url);
$arrays = explode("\n", $text);

$cleanArrs = array_filter($arrays, function($value) {
   return end(explode('.', $value)) == "csv";
});

function isSelected($a, $b){
    if ($a==$b){
        return "selected";
    }
    return "";
}

$selected_csv = isset($_GET["csv_file"])&&in_array($_GET["csv_file"], $cleanArrs) ? $_GET["csv_file"] : reset($cleanArrs);

?>

<html>
<head>
    <script src="plotly-latest.min.js"></script>
    <!-- <script src="https://cdn.plot.ly/plotly-latest.min.js"></script> -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="main.css">
    <title>Compton interactive plots</title>
    <!-- <script src="chart.js"></script> -->
</head>
<body>
    <div id="gd" style="height: max(80vh, 600px); padding-bottom: 20px;"></div>
            
    <form name="form" action="" method="get">
        <p style="text-align: center;">Select energy point:</p>
	<div style="margin: 0 auto; display: flex; justify-content: center;">
        <select name="season" class="select-css" style="margin: 0;" onchange="this.form.submit()">
            <? foreach($availableSeasons as $s){ ?>
            <option value="<?echo $s?>" <?echo isSelected($s, $season)?>><?echo $s?></option>
            <? } ?>
        </select>
        <select name="csv_file" class="select-css" style="margin: 0;" onchange="this.form.submit()">
            <? foreach($cleanArrs as $file){ ?>
            <option value="<?echo $file?>" <?echo isSelected($file, $selected_csv)?>><?echo $file?></option>
            <? } ?>
        </select>
	</div>
    </form>


    <script>
        function makeplot(){
            Plotly.d3.csv('<?echo $url_total_info;?>', (allRows)=>{
                const {mean_energy, mean_spread, mean_energy_stat_err} = parseResultsTable(allRows, "<?echo $selected_csv;?>");        
                Plotly.d3.csv('<?echo $url.$selected_csv;?>', function(data){processData(data, mean_energy, mean_spread, mean_energy_stat_err)});
            }
            );
        }
        
        function parseResultsTable(allRows, energy_point){
            // Extracts a row following the energy point in the total csv file (or null if energy point is not exists)
            data = energy_point.slice(0, -4).split('_');
	    for (var i=0; i<allRows.length; i++){
                if (allRows[i].first_run == data[1] ){
                    return allRows[i];
                }
            }
            return null;
        }
        
        function parseRow(row){
            // Parses a row from the detailed csv file
	    row['start_time'] = Date.parse(row['compton_start']);
            row['stop_time'] = Date.parse(row['compton_stop']);
            row['center_time'] = new Date((row['start_time'] + row['stop_time'])/2);
            row['timedelta'] = (row['stop_time'] - row['start_time'])/2/1000; // in seconds

	    text_energy = "E = " + parseFloat(row['e_mean']).toFixed(2) + "±" + parseFloat(row['e_std']).toFixed(2) + " MeV<br>";
	    text_spread = "spread = " + parseFloat(row['spread_mean']).toFixed(2) + "±" + parseFloat(row['spread_std']).toFixed(2) + " MeV<br>";
            text_str = text_energy + text_spread + "<b>Compton</b><br>" + "<i>Start: </i>" + 
                    row['compton_start'] + "<br><i>Stop: </i>" + row['compton_stop'] + "<br><br>";
            row['text_str'] = text_str + "<b>Runs: </b>" + row['run_first'] + " - " + row['run_last'] + "<br><br>";
            return row;
        }
        
        function processSpread(data, elementId, mean_value){
            let x = [], y = [], std_y = []
            for (var i=0; i<data.length; i++){
                const {center_time, spread_mean, spread_std} = parseRow(data[i]);
                x.push(center_time);
                y.push(spread_mean);
                std_y.push(spread_std);
            }
            makeSpreadPlot(elementId, x, y, std_y, mean_value);
        }
        
        function kde(x, y, w) {
            const ts = (t) => t.getTime()/1000;
            const toDateTime = (secs) => {
                let t = new Date(0);
                t.setSeconds(secs);
                return t;
            };
            const steps = 1000;
            const dt =  (ts(x[x.length - 1]) - ts(x[0]))/steps;
            const kernel = (x, x0, w0, y0) => {
                if (Math.abs(x-x0)>w0){
                    return 0;
                }
                return y0/w0;
                //return y0*3*(1-((x-x0)/w0/2)**2)/4;
            }; 
            const get_est = (timestamp) => {
                let val = 0
                for (var i=0; i<x.length; i++){
                    val += kernel(timestamp, ts(x[i]), w[i], y[i]);
                }
                return val;
            };
            //console.log(x, y);
            const timestamp_arr = Plotly.d3.range(steps).map(function(i){return ts(x[0])+i*dt;});
            
            let kdex = [];
            let kdey = [];
            for (var j=0; j<timestamp_arr.length; j++){
                kdex.push(toDateTime(timestamp_arr[j]));
                kdey.push(get_est(timestamp_arr[j]));
            }
            //console.log(kdex, kdey);
            return [kdex, kdey]
        }
        
        function oldAverage(E, L){
            //Averager by the old method with E and L only
            if (E.length !== L.length){
                return null;
            }
            let EL = 0;
            let sL = 0;
            for (let i = 0; i<E.length; i++){
                EL += parseFloat(E[i])*parseFloat(L[i]);
                sL += parseFloat(L[i]);
            }
            return EL/sL;
        }
        
        function processData(allRows, mean_energy, mean_spread, mean_energy_stat_err) {
            // Processes all data rows
            var dict = {};
            dict['x'] = [];
            dict['e_mean'] = [];
            dict['e_std'] = [];
            dict['spread_mean'] = [];
            dict['spread_std'] = [];
            dict['compton'] = [];
            dict['lum'] = [];
            dict['twidth'] = [];
            
            for (var i=0; i<allRows.length; i++){
                const row = parseRow(allRows[i]);
                                
                dict['x'].push( row['center_time'] );
                dict['e_mean'].push( row['e_mean'] );
                dict['e_std'].push( row['e_std'] );
                dict['spread_mean'].push( row['spread_mean'] );
                dict['spread_std'].push( row['spread_std'] );
                dict['compton'].push( row['text_str'] );
                dict['lum'].push( row['luminosity'] );
                dict['twidth'].push( row['timedelta'] );
            }
            
            const [a, b] = kde(dict['x'], dict['lum'], dict['twidth']);
            dict['kdex'] = a;
            dict['kdey'] = b;
            //console.log(dict['kdex'], dict['kdey']);
            //oldAverage(y, dict['lum']);
            
            dict['mean_energy_total'] = mean_energy;
            dict['old_mean_energy_total'] = oldAverage(dict['e_mean'], dict['lum']);
            dict['mean_spread_total'] = mean_spread;
	    dict['mean_energy_stat_err'] = mean_energy_stat_err;
            
            makePlotly(dict, "gd");
        }
        
        function makePlotly(dict, elementId){
            const getYRange = (y, std_y) => {
                const ys = [...y].sort();
                const std_ys = [...std_y].sort();
                let idx = Math.floor(ys.length/2);
                const y0 = parseFloat(ys[idx]);
                const std0 = parseFloat(std_ys[idx]);
                return [y0-6*std0, y0+6*std0];
            };
            
            var trace1 = {
                x: dict['x'],
                y: dict['e_mean'],
                yaxis: 'y3',
                mode: 'markers',
                text: dict['compton'],
                hovertemplate: "%{text}<br><br>" + "<extra></extra>",
                hovermode: "x",
                error_y: {
                    type: 'data',
                    array: dict['e_std'],
                    color: '#260101',
                },
                showlegend: false,
                marker: {
                    color: '#260101',
                },
                type: "scatter",
            };
            var trace2 = {
                x: dict['x'],
                y: dict['spread_mean'],
                yaxis: 'y2',
                mode: 'markers',
                text: dict['compton'],
                hovertemplate: "%{text}<br><br>" + "<extra></extra>",
                hovermode: "x",
                error_y: {
                    type: 'data',
                    array: dict['spread_std'],
                    color: '#260101',
                },
                showlegend: false,
                marker: {
                    color: '#260101',
                },
                type: "scatter",
            };
            var trace3 = {
                x: dict['kdex'],
                y: dict['kdey'],
                hovertemplate: "%{y}<br><br>" + "<extra></extra>",
                hovermode: "x",
                showlegend: false,
                marker: {
                    color: '#F23030',
                },
                line: {
                    shape: 'hvh',
                },
                type: "scatter",
            };
            var traces = [trace1, trace2, trace3];
            
            var updatemenus = [];
	    console.log(dict);
            if (dict['mean_energy_total']){
                updatemenus = [{
                buttons: [
                    {
                        args:[{'shapes[0].visible': true, 'shapes[1].visible': false, 'title': '<E> = ' + parseFloat(dict['mean_energy_total']).toFixed(3) + '±' + parseFloat(dict['mean_energy_stat_err']).toFixed(3) + ' MeV, ' + '<Spread> = ' + parseFloat(dict['mean_spread_total']).toFixed(3) + ' MeV',}],
                        label: 'Current average method',
                        method: 'relayout'
                    }, {
                        args:[{'shapes[0].visible': false, 'shapes[1].visible': true, 'title': '<E> = ' + parseFloat(dict['old_mean_energy_total']).toFixed(3) + ' MeV, ' + '<Spread> = ' + parseFloat(dict['mean_spread_total']).toFixed(3) + ' MeV',}],
                        label: 'Former average method',
                        method: 'relayout'
                    },
                ],
                direction: 'center',
                showactive: 'true',
                type: 'dropdown',
                y: 1.1,
                xanchor: 'left',
                yanchor: 'top',
                active: 0,
            }];
            }
            
            var layout = {
                title: '<E> = ' + parseFloat(dict['mean_energy_total']).toFixed(3) + '±' + parseFloat(dict['mean_energy_stat_err']).toFixed(3) + ' MeV, ' + '<Spread> = ' + parseFloat(dict['mean_spread_total']).toFixed(3) + ' MeV',
                updatemenus: updatemenus,
                font: {
                    size: 16,
                },
                xaxis: {
                    title: "Time, NSK",
                    automargin: true,
                },
                yaxis3: {
                    domain: [0.6, 1],
                    title: "Mean energy, MeV",
                    automargin: true,
                    //showspikes: true,
                    //spikemode: "across",
                    //spikesnap: "data",
                },
                yaxis2: {
                    domain: [0.3, 0.5],
                    title: "Spread, MeV",
                    autorange: false,
                    range: getYRange(dict['spread_mean'], dict['spread_std']),
                    //showspikes: true,
                    //spikemode: "across",
                    //spikesnap: "data",
                },
                yaxis: {
                    domain: [0, 0.2],
                    automargin: true,
                    zeroline: true,
                    rangemode: 'positive',
                    title: "L, nb<sup>-1</sup>/s",
                    hoverformat: '.2f',
                },
                paper_bgcolor: 'rgba(0,0,0,0)',
                plot_bgcolor: 'rgba(0,0,0,0)',
                autosize: true,
            };
            
            if (dict['mean_energy_total']){
                layout['shapes'] = [{
                    type: 'line',
                    yref: 'y3',
                    xref: 'paper',
                    x0: 0,
                    x1: 1,
                    y0: dict['mean_energy_total'],
                    y1: dict['mean_energy_total'],
                    line: {
                        color: '#590A0A',
                    },
                },
                {
                    type: 'line',
                    yref: 'y3',
                    xref: 'paper',
                    x0: 0,
                    x1: 1,
                    y0: dict['old_mean_energy_total'],
                    y1: dict['old_mean_energy_total'],
                    line: {
                        color: '#590A0A',
                    },
                    visible: false,
                },
                {
                    type: 'line',
                    yref: 'y2',
                    xref: 'paper',
                    x0: 0,
                    x1: 1,
                    y0: dict['mean_spread_total'],
                    y1: dict['mean_spread_total'],
                    line: {
                        color: '#590A0A',
                    },
                    visible: true,
                }];
            }
            
            Plotly.newPlot('gd', traces, layout, {modeBarButtonsToRemove: ['toImage'], responsive: true,});
            
        }
        
        makeplot();
        
    </script>

</body>
</html>
