import React from 'react';
import Tooltip from '../Tooltip';
import { st, classes } from './StackedBarChart.st.css.js';
import { stVars as colors } from '../Foundation/stylable/colors.st.css.js';
import { scaleLinear, scaleBand, } from 'd3-scale';
import { select } from 'd3-selection';
import { axisRight } from 'd3-axis';
import { format } from 'd3-format';
import { dataHooks } from './constants';
import Text from '../Text';
const defaultYAxisTickFormat = format(',');
const CONSTANTS = {
    top: 30,
    right: 30,
    bottom: 30,
    left: 100,
    gap: 18,
    barWidth: 48,
};
class StackedBarChart extends React.PureComponent {
    constructor(props) {
        super(props);
        this.colors = [colors.A1, colors.A2];
        this._getAmountOfBarsCanRender = (data = []) => {
            const { width = StackedBarChart.defaultProps.width } = this.props;
            const result = [];
            const availableWidthForBars = width - this.margin.left;
            const barWidth = CONSTANTS.barWidth + CONSTANTS.gap;
            const availableBarsForRender = Math.floor(availableWidthForBars / barWidth);
            for (let i = 0; i < availableBarsForRender; i++) {
                if (!!data[i]) {
                    result.push(data[i]);
                }
            }
            return result;
        };
        this._update = () => {
            const { data, yAxisTickFormat = StackedBarChart.defaultProps.yAxisTickFormat, width = StackedBarChart.defaultProps.width, } = this.props;
            const { svg, x, y } = this.state;
            // Data
            const _data = this._getAmountOfBarsCanRender(data).map(d => ({
                ...d,
                sum: d.values.reduce((a, b) => a + b, 0),
            }));
            const innerPadding = _data.length > 4 ? 0.8 : 0.75;
            const scalesPadding = 0.5;
            const scaleWidth = _data.length * (CONSTANTS.barWidth + CONSTANTS.gap) + CONSTANTS.gap;
            // Scales
            const _x = x
                .domain(_data.map(d => d.label))
                .range([0, scaleWidth])
                .paddingInner(innerPadding)
                .paddingOuter(scalesPadding)
                .round(true);
            const _y = y.domain([0, Math.max(..._data.map(d => d.sum))]);
            const yAxis = axisRight(_y)
                .tickSize(width)
                .tickFormat(d => yAxisTickFormat(d, defaultYAxisTickFormat(d)))
                .ticks(4);
            svg
                .select(`[data-hook="${dataHooks.yAxis}"]`)
                // @ts-expect-error some confusion between call signatures - generic gets lost?
                .call(yAxis)
                .selectAll('.tick text')
                .attr('x', -6)
                .attr('dy', 4);
            this.setState({
                data: _data,
                x: _x,
                y: _y,
                yAxis,
                width,
            });
        };
        this.chart = React.createRef();
        this.data = [];
        this.margin = Object.assign(CONSTANTS, props.margin);
        this.height = props.height ?? StackedBarChart.defaultProps.height;
        this.chartHeight = this.height - this.margin.top - this.margin.bottom;
        this.state = {
            data: [],
            x: scaleBand().range([0, props.weight]),
            y: scaleLinear().range([this.chartHeight, 0]),
            width: props.weight,
        };
    }
    componentDidMount() {
        this.setState({
            svg: select(this.chart.current),
        }, this._update);
    }
    componentDidUpdate(prevProps) {
        if (prevProps.data !== this.props.data) {
            this.setState({
                svg: select(this.chart.current),
            }, this._update);
            return true;
        }
        return false;
    }
    render() {
        const { tooltipTemplate, tooltipCommonProps, className, dataHook } = this.props;
        const { data, x, y, width } = this.state;
        return (React.createElement("div", { "data-hook": dataHook, className: st(classes.root, {}, className) },
            React.createElement("svg", { ref: this.chart, width: width, height: this.height },
                React.createElement("g", { "data-hook": dataHooks.yAxis, className: classes.yAxis, transform: `translate(${this.margin.left}, ${this.margin.top})` }),
                React.createElement("g", { "data-hook": dataHooks.bars, transform: `translate(${this.margin.left}, ${this.margin.top})` }, data.map((d, itemIndex) => {
                    let stacked = this.chartHeight;
                    return (React.createElement("g", { key: itemIndex }, d.values.map((value, index) => {
                        const height = this.chartHeight - y(value);
                        stacked -= height;
                        return (React.createElement("rect", { key: index, fill: this.colors[index], height: height, width: CONSTANTS.barWidth, x: x(d.label) - 25, y: stacked }));
                    })));
                }))),
            data &&
                data.map((d, index) => (React.createElement("div", { key: index, className: classes.textPosition, style: {
                        left: x(d.label) + this.margin.left - 25,
                        top: this.height - 15,
                    } },
                    React.createElement(Text, { textAlign: "center", skin: "standard", light: true, secondary: true, weight: "normal", size: "small", ellipsis: true, "data-hook": dataHooks.xAxis }, d.label)))),
            tooltipTemplate &&
                data.map((d, index) => (React.createElement("div", { key: index, className: classes.tooltip, style: {
                        left: x(d.label) + this.margin.left - 25,
                        top: y(d.sum) + this.margin.top,
                    } },
                    React.createElement(Tooltip, { ...tooltipCommonProps, content: tooltipTemplate(d), dataHook: dataHooks.tooltip },
                        React.createElement("button", { className: classes.tooltipInner, style: { height: `${this.chartHeight - y(d.sum)}px` } })))))));
    }
}
StackedBarChart.displayName = 'StackedBarChart';
StackedBarChart.defaultProps = {
    data: [],
    width: 900,
    height: 350,
    margin: CONSTANTS,
    tooltipCommonProps: {},
    yAxisTickFormat: defaultYAxisTickFormat,
};
export default StackedBarChart;
//# sourceMappingURL=StackedBarChart.js.map