<!doctype html>
<html ng-app="Application">

<head>
    <script>
        var OSProfilerData = $DATA;
    </script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
    <script src="https://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.js"></script>
    <style>
        .trace {
            min-width: 900px;
            width: 100%;
        }

        .trace tr:hover {
            background-color: #D9EDF7 !important;
        }

        .trace tr td {
            width: 14%;
            white-space: nowrap;
            padding: 2px;
            border-right: 1px solid #EEE;
        }

        .trace tr td.details {
            width: 10%;
            padding-right: 20px;
        }

        .trace.cursor_pointer_on_hover {
            cursor: pointer;
        }

        .trace .level {
            width: 10%;
            font-weight: bold;
        }

        .bold {
            font-weight: bold;
        }

        .duration {
            width: 25px;
            margin: 0px;
            padding: 0px;
            background-color: #C6EFF3;
            border-radius: 4px;
            font-size: 10px;
        }

        .duration div {
            padding-top: 4px;
            padding-bottom: 4px;
            text-align: center;
        }

    </style>
    <script type="text/ng-template" id="tree_item_renderer.html">
        <div ng-init="hide_children=false">
            <table class="trace cursor_pointer_on_hover">
                <tr>
                    <td class="level" style="padding-left: {{data.level * 5}}px;">
                        <button type="button" class="btn btn-default btn-xs" ng-disabled="data.is_leaf" ng-click="hide_children=!hide_children">
                            <span class="glyphicon glyphicon-{{(data.is_leaf) ? 'cloud' : ((hide_children) ? 'plus': 'minus')}}"></span>
                            {{data.level || 0}}
                        </button>
                    </td>
                    <td ng-click="display(data)" class="text-center">
                        <div class="duration" style="width: {{get_width(data)}}%; margin-left: {{get_started(data)}}%;">
                            <div>{{data.info.finished - data.info.started}} ms</div>
                        </div>
                    </td>
                    <td ng-click="display(data)" class="{{is_important(data) ? 'bold' : ''}} text-right">{{data.info.name}}</td>
                    <td ng-click="display(data)">{{data.info.project || "n/a"}}</td>
                    <td ng-click="display(data)">{{data.info.service || "n/a"}}</td>
                    <td ng-click="display(data)">{{data.info.host || "n/a"}}</td>
                    <td class="details">
                        <a href="#" ng-click="display(data)">Details</a>
                    </td>
                </tr>
            </table>
            <div ng-hide="hide_children">
                <div ng-repeat="data in data.children" ng-include="'tree_item_renderer.html'"></div>
            </div>
        </div>
    </script>
    <script>
        angular.module('Application', ['ui.bootstrap']);

        function ProfilerCtlr($scope, $modal) {
            var convert_input = function(input, level) {
                level = (level) ? level : 0;
                input.level = level;
                input.is_leaf = !input.children.length;

                for (var i = 0; i < input.children.length; i++) {
                    convert_input(input.children[i], level + 1);
                }
                return input;
            };

            $scope.get_width = function(data) {
                var full_duration = $scope.tree[0].info.finished;
                var duration = (data.info.finished - data.info.started) * 100.0 / full_duration;
                return (duration >= 0.5) ? duration : 0.5;
            };

            $scope.get_started = function(data) {
                var full_duration = $scope.tree[0].info.finished;
                return data.info.started * 100.0 / full_duration;
            };

            $scope.is_important = function(data) {
                return ['total', 'wsgi', 'rpc'].indexOf(data.info.name) != -1;
            };

            $scope.display = function(data) {
                var info = angular.copy(data.info);

                var metadata = {};
                angular.forEach(info, function(value, key) {
                    var parts = key.split('.');
                    if (parts[0] == 'meta') {
                        if (parts.length == 2) {
                            this[parts[1]] = value;
                        } else {
                            var group_name = parts[1];
                            if (!(group_name in this)) {
                                this[group_name] = {};
                            }

                            this[group_name][parts[2]] = value;
                        }
                    };
                }, metadata);

                info.duration = info.finished - info.started;
                info.metadata = '<pre>' + JSON.stringify(metadata, '', 4) + '</pre>';

                var trace_data = '<div class="row">';
                var columns = [
                    'name', 'project', 'service', 'host', 'started',
                    'finished', 'duration', 'exception', 'metadata'
                ];

                for (var i = 0; i < columns.length; i++) {
                    trace_data += '<div class="col-md-2 text-right text-capitalize"><strong>' +
                        columns[i] + '</strong></div>';
                    trace_data += '<div class="col-md-10 text-left">' +
                        info[columns[i]] + '</div>';
                }
                trace_data += '</div>';

                var output = '<div class="modal-header text-center">' +
                    '<h3>Trace Point Details</h3></div>' +
                    '<div class="modal-body">' + trace_data + '</div>' +
                    '<div class="modal-footer"><span class="glyphicon glyphicon-cloud">' +
                    '</span></div>';

                var modal_instance = $modal.open({
                    'template': output,
                    'size': 'lg'
                });
            };

            $scope.tree = [convert_input(OSProfilerData)];
        }
    </script>
</head>

<body>
    <div ng-controller="ProfilerCtlr">
        <table class="trace">
            <tr class="bold text-left" style="border-bottom: solid 1px gray;">
                <td class="level">Levels</td>
                <td>Duration</td>
                <td class="text-right">Type</td>
                <td>Project</td>
                <td>Service</td>
                <td>Host</td>
                <td class="details">Details</td>
            </tr>
        </table>
        <div ng-repeat="data in tree" ng-include="'tree_item_renderer.html'"></div>
    </div>
</body>

</html>
