var Dashboard = React.createClass({
    getInitialState: function() {
        return {};
    },

    componentDidMount: function() {
        this.reload();
    },

    reload: function() {
        getURL("http://127.0.0.1:6464/stats.json", {}, function(resp) {
            var newState = {};
            var decode = function(point) {
                return {
                    timestamp: point[0],
                    processed: point[1],
                    errors:    point[2],
                    min:       point[3],
                    p25:       point[4],
                    mean:      point[5],
                    median:    point[6],
                    p75:       point[7],
                    max:       point[8],
                }
            };
            for (name in resp) {
                newState[name] = resp[name].map(decode);
            }
            this.setState(newState);
            setTimeout(this.reload, 3000);
        }.bind(this));
    },

    renderDaemons: function() {
        var daemons = [];
        for (name in this.state) {
            daemons.push(<Daemon name={name} key={name} points={this.state[name]} />);
        }

        return daemons;
    },

    render: function() {
        return (
            <div className="daemons">{this.renderDaemons()}</div>
        );
    }
});

var Daemon = React.createClass({
    render: function() {
        var last = this.props.points[this.props.points.length - 1];
        return (
            <div className="daemon">
                <div className="left-block">
                    <h1>{this.props.name}</h1>
                    <dl>
                        <dt>Processed:</dt><dd>{last.processed}</dd>
                        <dt>Errors:</dt><dd>{last.errors}</dd>
                        <dt>Median:</dt><dd>{formatDuration(last.median)}</dd>
                    </dl>
                </div>
                <BoxPlot points={this.props.points} />
                <LineChart points={this.props.points} />
            </div>
        );
    }
});

var BoxPlot = React.createClass({
    render: function(){
        var points = this.props.points,
            maxHeight = 140,
            padding = 5;

        var min, max;
        points.map(function(point) {
            if (min === undefined || point.min < min) {
                min = point.min;
            }
            if (max === undefined || point.max > max) {
                max = point.max;
            }
        });

        var renderBox = function(point, i) {
            var relativeY = function(val) {
                return maxHeight - Math.round((val-min)/(max-min) * maxHeight) + padding;
            };

            var width = 10;
            var padding = 5;

            var x1 = (width + padding) * i + padding;
            var x2 = x1 + width;
            var minY = relativeY(point.min);
            var p25Y = relativeY(point.p25);
            var medianY = relativeY(point.median);
            var p75Y = relativeY(point.p75);
            var maxY = relativeY(point.max);

            return (
                <g key={i}>
                    <line key="max"
                        x1={x1+2}
                        x2={x2-2}
                        y1={maxY}
                        y2={maxY}
                        strokeWidth={1}
                        style={{stroke: "#aaa"}} />
                    <line key="max-bar"
                        x1={x1+width/2}
                        x2={x1+width/2}
                        y1={maxY}
                        y2={p75Y}
                        strokeDasharray="3,1"
                        strokeWidth={1}
                        style={{stroke: "#ccc"}} />
                    <rect key="iqr"
                        x={x1}
                        y={p75Y}
                        width={width}
                        height={p25Y - p75Y}
                        strokeWidth={1}
                        style={{fill: "#f0f0f0", stroke: "#888"}} />
                    <line key="median"
                        x1={x1}
                        x2={x2}
                        y1={medianY}
                        y2={medianY}
                        strokeWidth={2}
                        style={{stroke: "#444"}} />
                    <line key="min-bar"
                        x1={x1+width/2}
                        x2={x1+width/2}
                        y1={minY}
                        y2={p25Y}
                        strokeDasharray="3,1"
                        strokeWidth={1}
                        style={{stroke: "#ccc"}} />
                    <line key="min"
                        x1={x1+2}
                        x2={x2-2}
                        y1={minY}
                        y2={minY}
                        strokeWidth={1}
                        style={{stroke: "#aaa"}} />
                </g>
            );
        };
        return (
            <div className="boxplot">
                <svg width="455" height="150">
                    {this.props.points.map(renderBox)}
                </svg>
            </div>
        );
    }
});

var LineChart = React.createClass({
    render: function() {
        var points = this.props.points,
            maxHeight = 140,
            padding = 5,
            colors = {processed: "#46f", errors: "#f64"};

        var min = 0, max;
        points.map(function(point) {
            if (max === undefined || point.processed > max) {
                max = point.processed;
            }
        });

        var makePath = function(points, key) {
            if (max === 0) {
                return;
            }

            var path = points.map(function(point, i) {
                var val = point[key];
                var width = 15;
                var x = i * width;
                var y = maxHeight - Math.round((val-min)/(max-min) * maxHeight) + padding;

                if (i === 0) {
                    return "M"+x+","+y;
                } else {
                    return "L"+x+","+y;
                }
            });

            return (
                <path
                    d={path.join(" ")}
                    strokeWidth={2}
                    style={{stroke: colors[key], fill: "transparent"}} />
            );
        };

        return (
            <div className="linechart">
                <svg width="455" height="150">
                    {makePath(points, "processed")}
                    {makePath(points, "errors")}
                </svg>
            </div>
        );
    }
});

ReactDOM.render(<Dashboard />, document.getElementById("app"));