import * as d3 from "d3";
import StackedbarOptions from './StackedbarOptions';
import { getDigit, getLetter } from '../../../support/Strings';
var Stackedbar = /** @class */ (function () {
    function Stackedbar(options) {
        if (options === void 0) { options = new StackedbarOptions(); }
        this.idMap = new Map();
        this.options = options;
    }
    Stackedbar.prototype.render = function () {
        var div = document.createElement("div");
        div.classList.add("lto-vis-stackedbar");
        div.innerHTML = "<svg width=" + this.options.width + " height=" + this.options.height + "></svg>";
        return div;
    };
    Stackedbar.prototype.init = function (element) {
        var _this = this;
        this.options.data.then(function (data) {
            var svg = d3.select(element.querySelector("svg"));
            var margin = { top: 20, right: 20, bottom: 50, left: 40 };
            var width = +svg.attr("width") - margin.left - margin.right;
            var height = +svg.attr("height") - margin.top - margin.bottom;
            var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
            var x = d3.scaleBand().rangeRound([0, width]).padding(0.1).align(0.1);
            var y = d3.scaleLinear().rangeRound([height, 0]);
            var layers;
            var rect;
            if (_this.options.sort) {
                data.sort(function (a, b) { return b.total - a.total; });
            }
            var columns = _this.getLabels(data);
            var numStates = data.length;
            var stack = d3.stack().keys(columns);
            layers = stack(data).map(function (layer) { return layer.map(function (e, i) {
                return {
                    type: e.data.type,
                    x: i,
                    y: _this.getValues(columns, e.data)[columns.indexOf(layer.key)],
                    column: layer.key
                };
            }); });
            for (var s = 0; s < numStates; ++s) {
                var y0 = 0;
                for (var ag = 0; ag < columns.length; ++ag) {
                    var e = layers[ag][s];
                    e.y0 = y0;
                    y0 += e.y;
                }
            }
            /*
             * Calculate the maximum of the total populations,
             * and the maximum of the age groups.
             */
            // const yGroupMax = d3.max(layers, (layer: any) => d3.max(layer, (d: any) => d.y));
            var yStackMax = d3.max(layers, function (layer) { return d3.max(layer, function (d) { return d.y0 + d.y; }); });
            /*
             * Set the domains for the x-, y-axis and categorical color scales.
             */
            x.domain(data.map(function (d) { return d.type; }));
            // @ts-ignore
            y.domain([0, d3.max(data, function (d) { return _this.sumup(d); })]).nice();
            /*
             * Render the bars.
             */
            g.selectAll(".serie")
                .data(layers)
                .enter().append("g")
                .attr("class", function (d) { return "serie lto-vis-" + getDigit(_this.idMap, d[0].column) + " lto-vis-" + getLetter(_this.idMap, d[0].column); })
                .selectAll("rect")
                .data(function (d) { return d; })
                .enter().append("rect")
                .attr("x", function (d) { return x(d.type); })
                .attr("y", height)
                .attr("width", x.bandwidth())
                .attr("height", 0);
            rect = g.selectAll("rect");
            // Initial animation to gradually "grow" the bars from the x-axis.
            rect.transition()
                .delay(function (d, i) { return i; })
                .attr("y", function (d) { return y(d.y0 + d.y); })
                .attr("height", function (d) { return y(d.y0) - y(d.y0 + d.y); })
                .attr("class", function (d) { return d.column; });
            // add svg title for tooltip support
            rect.append("svg:title")
                .text(function (d) { return d.type + ", " + d.column + ": " + d.y + " (total: " + _this.sumup(d) + ")"; });
            if (_this.options.showAxis) {
                /*
                 * X-axis set-up.
                 * Note that we do not set up the Y-axis, since the bar heights are
                 * scaled dynamically.
                 */
                g.append("g")
                    .attr("class", "axis axis--x")
                    .attr("transform", "translate(0," + height + ")")
                    .call(d3.axisBottom(x));
                // Add labels to the axes.
                svg.append("text")
                    .attr("class", "axis axis--x")
                    .attr("text-anchor", "middle")
                    .attr("transform", "translate(" + (width / 2) + "," + (height + 60) + ")")
                    .text(_this.options.textX);
                svg.append("text")
                    .attr("class", "axis axis--y")
                    .attr("text-anchor", "middle")
                    .attr("transform", "translate(0," + (height / 2) + ")rotate(-90)")
                    .attr("dy", "20.0")
                    .text(_this.options.textY);
            }
            if (_this.options.showLegend) {
                var legend = g.selectAll(".legend")
                    .data(columns.reverse())
                    .enter().append("g")
                    .attr("class", "legend")
                    .attr("transform", function (d, i) { return "translate(" + ((i % 4) * 100) + ", " + (Math.floor(i / 4) * 20) + ")"; });
                legend.append("rect")
                    .attr("x", 0)
                    .attr("width", 18)
                    .attr("height", 18)
                    .attr("class", function (d) { return "serie lto-vis-" + getDigit(_this.idMap, d) + " lto-vis-" + getLetter(_this.idMap, d); });
                legend.append("text")
                    .attr("x", 20)
                    .attr("y", 9)
                    .attr("dy", ".35em")
                    .attr("text-anchor", "start")
                    .text(function (d) { return d; });
            }
            _this.transitionStacked(x, y, rect, parseFloat(yStackMax));
        });
    };
    /*
     * Reset the domain for the y-axis scaling to maximum of the population totals,
     * transition the y-axis changes to the bar heights, and then transition the
     * x-axis changes to the bar widths.
     */
    Stackedbar.prototype.transitionStacked = function (x, y, rect, yStackMax) {
        y.domain([0, yStackMax]);
        rect.transition()
            .duration(500)
            .delay(function (d, i) { return i; })
            .attr("y", function (d) { return ((y(d.y0 + d.y) * 0.85) + 40); })
            .attr("height", function (d) { return (y(d.y0) - y(d.y0 + d.y)) * 0.85; })
            .transition()
            .attr("x", function (d) { return x(d.type); })
            .attr("width", x.bandwidth());
    };
    Stackedbar.prototype.sumup = function (data) {
        var sum = 0.0;
        Object.keys(data).forEach(function (key) {
            if (typeof data[key] === "number") {
                sum += data[key];
            }
        });
        return sum;
    };
    Stackedbar.prototype.getLabels = function (data) {
        var labels = [];
        data.forEach(function (e) {
            e.labels.forEach(function (key) {
                if (key !== "type") {
                    if (labels.indexOf(key) < 0) {
                        labels.push(key);
                    }
                }
            });
        });
        return labels;
    };
    Stackedbar.prototype.getValues = function (labels, data) {
        var values = Array.from({ length: labels.length }, function () { return 0; });
        data.labels.forEach(function (key) {
            var index = labels.indexOf(key);
            values[labels.indexOf(key)] = data.values.length > index ? data.values[index] : 0;
        });
        return values;
    };
    return Stackedbar;
}());
export default Stackedbar;
//# sourceMappingURL=Stackedbar.js.map