<link rel="stylesheet" href="https://yastatic.net/bootstrap/3.3.1/css/bootstrap.min.css">
<script src="https://yandex.st/jquery/2.0.3/jquery.min.js"></script>
<script src="https://yastatic.net/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<style type='text/css'>
.progress {
    margin-bottom: 0px;
}
.warning {
    background-color: #f0ad4e
}
.danger {
    background-color: red;
}
.normal {
    background-color: #d4ff33
}
.very_danger {
    background-color: brown;
    color: white;
}
td.clock-cell {
    font: 16pt bolt;
    color: #880000;
    text-align: center;
}
table {
    border-spacing: 2px;
    border-collapse: separate;
}
</style>
<script type="text/javascript">
    var saved_queues = "";
    var saved_proxies = "";
    var saved_shards = "";
    $(document).ready(function(){
        try{
            document.getElementById("services_list_column").setAttribute("width", "1%");
            document.getElementById("main_info_column").setAttribute("width", "95%");
        } catch(err){
            console.log(err);
        }
    });
    window.onload = function() {
        disable_links = false;
        koolajax.callback(build_proxies(), onDoneRebuildProxies);
        koolajax.callback(build_iproxy_queues(), onDoneRebuildQueues);
        koolajax.callback(build_services(), onDoneRebuildServices);
    }
    function onDoneRebuildQueues(s) {
        if (s !== saved_queues) {
            document.getElementById("queues").innerHTML = s;
            saved_queues = s;
        }
        setTimeout(function() {
            koolajax.callback(build_iproxy_queues(), onDoneRebuildQueues);
        }, 1000);
    }
    function onDoneRebuildProxies(s) {
        if (s !== saved_proxies) {
            document.getElementById("proxy_states").innerHTML = s;
            saved_proxies = s;
        }
        setTimeout(function() {
            koolajax.callback(build_proxies(), onDoneRebuildProxies);
        }, 1000);
    }
    function onDoneRebuildServices(s) {
    //alert("services");
        if (s !== saved_shards) {
            document.getElementById("service_repshards").innerHTML = s;
            saved_shards = s;
        }
        setTimeout(function() {
            koolajax.callback(build_services(), onDoneRebuildServices);
        }, 1000);
    }
</script>

<?php
date_default_timezone_set("Europe/Moscow");
function getTime() {
    return date('G:i:s');
}

function cmp_queues($q1, $q2){
        if ($q2["space_bytes"] > $q1["space_bytes"]){
            return 1;
        } else if($q2["space_bytes"] < $q1["space_bytes"]){
            return -1;
        } else return 0;
    }
function number_human_readable ($number) {
    $res_number = $number;
    $color_class = "normal";
    if ($number / 1000000000000 > 1.5) {
        $res_number = round($number / 1000000000000, 1) . "T";
        $color_class = "very_danger";
    } else if ($number / 1000000000 > 1.5) {
        $res_number = round($number / 1000000000, 1) . "G";
        $color_class = "danger";
    } else if ($number / 1000000 > 1.5) {
        $res_number = round($number / 1000000, 1) . "M";
        $color_class = "warning";
    } else if ($number / 1000 > 1.5) {
        $res_number = round($number / 1000, 1) . "K";
        $color_class = "normal";
    }
    return array("number" => $res_number, "color_class" => $color_class);
}

function get_daily_index_color_class($ratio) {
    if ($ratio > 5) { return "very_danger"; }
    if ($ratio > 1) { return "danger"; }
    if ($ratio > 0.2) { return "warning"; }
    if ($ratio >= 0) { return "normal"; }
    return "warning";
}

function get_index_rates($ctype){
    try {
        $monitor_http = "http://saas-mon.n.yandex-team.ru/golovan_index_rates";
        $http = HttpRequest::get(
            $monitor_http . "?ctype=$ctype&dm=" . get_dm_url()
            )->connectTimeout(1)->readTimeout(60);
        return ["success" => ($http->ok()), "reply" => ($http->body())];
    } catch (Exception $e) {
        return ["success" => false, "reply" => ($e->getMessage())];
    }
}

function build_iproxy_queues(){
    global $ctype_cgi;
    read_reply_from_dm("dashboard?command=get_info_server&service=indexerproxy&service_type=indexerproxy&ctype=$ctype_cgi&filter=host,result.queues&groupings=service_to(docs@summ,space_bytes@summ);backend&categories=@indexerproxy.slot.@result.@queues.service_to.backend&report_slots=no&flat_report=no",
                        $json_queues_data);
    $queues_data = json_decode($json_queues_data, true);
    $ind_rates = array();
    try {
        $ind_rates_req = get_index_rates($ctype_cgi);
        if ($ind_rates_req["success"]) {
            $ind_rates = json_decode($ind_rates_req["reply"], true)["result"];
        }
    } catch (Exception $e) {}

    uasort($queues_data, 'cmp_queues');
    setlocale(LC_ALL, 'ru_RU');
    $result = "<table border='2'><tr><td class='clock-cell'>" . getTime() . "</td><td>bytes</td><td>docs</td><td>docs/daily</td>";
    foreach($queues_data as $serv => $que){
        $result .= "<tr><td>" . get_service_href_html($serv, "rtyserver") . "</td>";
        $qbytes_hr = number_human_readable($que["space_bytes"]);
        $result .= "<td class=" . $qbytes_hr['color_class'] . ">" . $qbytes_hr['number'] . "</td>";
        $qdoc_hr = number_human_readable($que["docs"]);
        $result .= "<td class=" . $qdoc_hr['color_class'] . ">" . $qdoc_hr['number'] . "</td>";
        if (array_key_exists("$serv", $ind_rates)) {
            if ($ind_rates["$serv"] > 0) {
                $ratio = round($que["docs"] / $ind_rates["$serv"], 2);
            } else {
                if ($que["docs"] > 0){ $ratio = 100500; } else { $ratio = 0; }
            }
            $result .= "<td class=" . get_daily_index_color_class($ratio) . ">" . $ratio . "</td></tr>";
        } else {
            $result .= "<td>-</td></tr>";
        }
    }
    $result .= "</table>";
    return $result;
}

function states_bar_code($r, $title=""){
    $title_popup = ($title == "") ? "" : "title='$title'";
            $repeats_label = (array_key_exists("repeat", $r) && $r["repeat"] > 1) ? $r["repeat"] . "x" : "";
    return "<div class=\"progress\" $title_popup>
        <div class=\"progress-bar progress-bar-danger\" role=\"progressbar\" aria-valuenow=\"70\" 
        aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width:$r[downs_perc]%\">$r[downs]</div>
        <div class=\"progress-bar progress-bar-warning\" role=\"progressbar\" aria-valuenow=\"70\" 
        aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width:$r[other_perc]%\">$r[other]</div>
        <div class=\"progress-bar progress-bar-info\" role=\"progressbar\" aria-valuenow=\"70\"
        aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width:$r[flagged_perc]%\">$r[flagged]</div>
        <div class=\"progress-bar progress-bar-success\" role=\"progressbar\" aria-valuenow=\"70\"
        aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width:$r[alives_perc]%\">
        $repeats_label$r[alives]</div>
        </div>";
}

function do_hosts_stat($state){
    $cnts = $state["result.controller_status"];

    $alives = array_key_exists("Active", $cnts) ? $cnts["Active"] : 0;
    $downs = array_key_exists("Down", $cnts) ? $cnts["Down"] : 0;
    $flagged = array_key_exists("Flagged", $cnts) ? $cnts["Flagged"] : 0;
    $other = 0;
    foreach($cnts as $key => $val){
            if ($key != "Active" && $key != "Down" && $key != "Flagged"){
                $other = $other + $val;
            }
        }
    $all = $alives + $downs + $flagged + $other;
    $dperc = ($all > 0) ? (100 * $downs / ($all)) : 0;
    $aperc = ($all > 0) ? (100 * $alives / ($all)) : 0;
    $fperc = ($all > 0) ? (100 * $flagged / ($all)) : 0;
    $operc = ($all > 0) ? (100 * $other / ($all)) : 0;

    return array("alives" => $alives, "downs" => $downs, "flagged" => $flagged, "other" => $other, "all" => $all,
                 "alives_perc" => $aperc, "downs_perc" => $dperc, "flagged_perc" =>  $fperc, "other_perc" => $operc);
}

function get_service_href_html($service_name, $service_type) {
    global $ctype_cgi;
    if ($ctype_cgi == "") {
        return htmlspecialchars($service_name);
    }
    return "<a href=\"" . get_service_url($service_name, $ctype_cgi, $service_type, "service_cluster_info") ."\">" . htmlspecialchars($service_name) . "</a>";
}

function build_proxy_statuses($proxy_kind){
    global $ctype_cgi;
    read_reply_from_dm("dashboard?command=get_status&service=$proxy_kind&service_type=$proxy_kind&ctype=$ctype_cgi&groupings=\$datacenter_alias\$(result.controller_status@facet)&report_slots=no&flat_report=no",
                        $json_proxies_data);
    $proxies_data = json_decode($json_proxies_data, true);
    if (!is_array($proxies_data)){
        return "<div>not array $proxies_data</div>";
    }
    $result = "<div style=''><table border='2'><tr><td>" . get_service_href_html($proxy_kind, $proxy_kind) . "</td>";
    $result_alives = "<tr><td class='clock-cell'>" . getTime() . "</td>";
    $result_downs = "<tr><td>downs</td>";
    foreach($proxies_data as $dc => $state){
        $result .= "<td>$dc</td>";
        $hosts_counts = do_hosts_stat($state);
        $js = states_bar_code($hosts_counts);
        $result_alives .= "<td>$js</td>";
    //    $result_alives .= "<td>$alives</td>";
        $result_downs .= "<td>$hosts_counts[downs]</td>";
    }
    $result_alives .= "</tr>";
    $result_downs .= "</tr>";
    $result .= "</tr>";
    $result .= $result_alives;
//    $result .= $result_downs;
    $result .= "</table></div>";
    return $result;
}
function build_proxies(){
    $result = "<table><tr><td>";
    $result .= build_proxy_statuses("indexerproxy");
    $result .= "</td><td>";
    $result .= build_proxy_statuses("searchproxy");
    $result .= "</td></tr></table>";
    return $result;
}

function join_alive_shards($states){
    $joined = array();
    $prev = array("all" => -1, "alives" => -1);
    foreach($states as $state){
        $state["repeat"] = 1;
        if (false && $prev["all"] == $state["all"] && $prev["alives"] == $state["alives"] && $state["all"] == $state["alives"]){
            $prev = array_pop($joined);
            $prev["title"] .= ", " . $state["title"];
            $prev["repeat"] += 1;
            $joined[] = $prev;
        } else {
            $joined[] = $state;
            $prev = $state;
        }
    }
    return $joined;
}

function cmp_fail_metrics($a, $b){
    return $b["metric"] - $a["metric"];
}
function cmp_reps($a, $b){
    return (4 * $b["downs_perc"] + 2 * $b["other_perc"] + $b["flagged_perc"]) - (4 * $a["downs_perc"] + 2 * $a["other_perc"] + $a["flagged_perc"]);
}

function build_service_repshards($bywhat){
    global $ctype_cgi;
    $by_part = "";
    $arr_key = "";
    if ($bywhat == "replicas"){
        $by_part = "service;\$datacenter_alias\$;replic_id(result.controller_status@facet)";
        $arr_key = "datacenter_aliass";
    } else if ($bywhat == "shards") {
        $by_part = "service;interval(result.controller_status@facet)";
        $arr_key = "intervals";
    } else {
        return "error: must be 'replicas' or 'shards' parameter";
    }
    read_reply_from_dm("dashboard?command=get_status&service=*&service_type=rtyserver&ctype=$ctype_cgi&groupings=$by_part&report_slots=no&flat_report=no&report_flagged=1", $json_data);
    $data = json_decode($json_data, true);
    if (!is_array($data)){
        return "not array: $data";
    }
    ksort($data);
    //$result = "<table border='2'><tr><td>Service-$bywhat</td><td></td></tr>";
    $reps_rows = "";
    $service_rows = array();

    foreach($data as $serv => $parts){
        $serv_data = array_key_exists($arr_key, $parts) ? $parts[$arr_key] : array();
        if (!is_array($serv_data)){
            $serv_rows[$serv] = "<td>not array: $serv</td>";
            continue;
        }
        $serv_counts = array();
        $perc_max = 0;
        $fail_metric = 0;
        ksort($serv_data);
        foreach($serv_data as $divis => $state){

            if ($bywhat == "replicas"){
                foreach($state["replic_ids"] as $repid => $repstate){
                    $hosts_count = do_hosts_stat($repstate);
                    $hosts_count["title"] = $divis . "(id=$repid)";
                    $serv_counts[] = $hosts_count;
                    $perc_max = max($perc_max, $hosts_count["downs_perc"] + $hosts_count["other_perc"]/2 + $hosts_count["flagged_perc"]/4);
                    $fail_metric = $fail_metric + $hosts_count["downs_perc"] + $hosts_count["other_perc"] + $hosts_count["flagged_perc"];
                }
            } else {
                $hosts_count = do_hosts_stat($state);
                $hosts_count["title"] = $divis;
                $serv_counts[] = $hosts_count;
                $perc_max = max($perc_max, $hosts_count["downs_perc"] + $hosts_count["other_perc"]/2 + $hosts_count["flagged_perc"]/4);
                $fail_metric = $fail_metric + $hosts_count["downs_perc"] + $hosts_count["other_perc"] + $hosts_count["flagged_perc"];
            }
        }
        $fail_metric = $fail_metric/count($serv_data) + 100 * $perc_max;
        $serv_counts_compact = join_alive_shards($serv_counts);
        uasort($serv_counts_compact, 'cmp_reps');

        $per_row = 15;
        $cur_col = 0;
        $serv_row = "<tr>";
        foreach($serv_counts_compact as $sc){
            if ($cur_col == $per_row){
                $cur_col = 0;
                $serv_row .= "</tr><tr>";
            }
            $cur_col += 1;
            $js = states_bar_code($sc, $sc["title"]);
            $serv_row .= "<td>$js</td>";
        }
        $serv_row .= "</tr>";
        $serv_rows[$serv] = array("table" => "<table><tr>" . $serv_row . "</tr></table>", "metric" => $fail_metric);
    }
    return $serv_rows;
}
function build_replicas(){
    return build_service_repshards("replicas");
}
function build_shards(){
    return build_service_repshards("shards");
}

function cmp_joined_servs($s1, $s2){
    return ($s2["replicas"]["metric"] + $s2["shards"]["metric"]) - ($s1["replicas"]["metric"] + $s1["shards"]["metric"]);
}

function join_repshards($reps, $shards){
    $result = array();
    $zero_arr = array("metric" => 0, "table" => "");
    foreach($reps as $serv => $rep){
        $result[$serv] = array("replicas" => $rep, "shards" => $zero_arr);
    }
    foreach($shards as $serv => $shard){
        if (!array_key_exists($serv, $result)){
            $result[$serv] = array("replicas" => $zero_arr);
        }
        $result[$serv]["shards"] = $shard;
    }

    uasort($result, 'cmp_joined_servs');
    return $result;
}

function build_services(){
    $result_data = array();
    $replicas_data = build_replicas();
    $shards_data = build_shards();

    $result_data = join_repshards($replicas_data, $shards_data);
//    $result_data = array();
    $result = "<table border='2'><tr><td class='clock-cell'>" . getTime() . "</td><td>Replicas</td><td>Shards</td></tr>";
    foreach($result_data as $serv => $serv_tables){
        $result .= "<tr>";
        $result .= "<td>" . get_service_href_html($serv, "rtyserver") . "</td>";
        $rt = $serv_tables["replicas"]["table"];
        $st = $serv_tables["shards"]["table"];
        $result .= "<td>$rt</td>";
        $result .= "<td>$st</td>";
        $result .= "</tr>";
    }
    $result .= "</table>";
    return $result;
}

function renderClusterReport() {
    $report_cluster = "";
    $report_cluster .= "<div id='proxy_states'>";
    $report_cluster .= build_proxies();
    $report_cluster .= "</div>";
    $report_cluster .= "<table><tr><td>";
    $report_cluster .= "<div id='service_repshards'>";
    $report_cluster .= build_services();
    $report_cluster .= "</div>";
    $report_cluster .= "</td><td style='vertical-align: top'>";
    $report_cluster .= "<div id='queues'>";
    $report_cluster .= build_iproxy_queues();
    $report_cluster .= "</div>";
    $report_cluster .= "</td></tr></table>";
    return $report_cluster;
}


$koolajax->scriptFolder = $KoolControlsFolder . "/KoolAjax";
$koolajax->enableFunction("build_iproxy_queues");
$koolajax->enableFunction("build_proxies");
$koolajax->enableFunction("build_services");
?>
