import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { ColorPicker, EditableText, IconButton, Size, Type } from 'browndash-components';
import * as d3 from 'd3';
import { IReactionDisposer, action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { FaFillDrip } from 'react-icons/fa';
import { Doc, NumListCast, StrListCast } from '../../../../../fields/Doc';
import { List } from '../../../../../fields/List';
import { listSpec } from '../../../../../fields/Schema';
import { Cast, DocCast, StrCast } from '../../../../../fields/Types';
import { Docs } from '../../../../documents/Documents';
import { undoable } from '../../../../util/UndoManager';
import { ObservableReactComponent } from '../../../ObservableReactComponent';
import { PinProps, PinDocView } from '../../../PinFuncs';
import { scaleCreatorNumerical, yAxisCreator } from '../utils/D3Utils';
import './Chart.scss';

export interface HistogramProps {
    Document: Doc;
    layoutDoc: Doc;
    axes: string[];
    titleCol: string;
    records: { [key: string]: any }[];
    width: number;
    height: number;
    dataDoc: Doc;
    fieldKey: string;
    margin: {
        top: number;
        right: number;
        bottom: number;
        left: number;
    };
}

@observer
export class Histogram extends ObservableReactComponent<HistogramProps> {
    private _disposers: { [key: string]: IReactionDisposer } = {};
    private _histogramRef: HTMLDivElement | null = null;
    private _histogramSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined;
    private numericalXData: boolean = false; // whether the data is organized by numbers rather than categoreis
    private numericalYData: boolean = false; // whether the y axis is controlled by provided data rather than frequency
    private maxBins = 15; // maximum number of bins that is readable on a normal sized doc
    @observable _currSelected: any | undefined = undefined; // Object of selected bar
    private curBarSelected: any = undefined; // histogram bin of selected bar for when just one bar is selected
    private selectedData: any[] = []; // array of selected bars
    private hoverOverData: any = undefined; // Selection of bar being hovered over

    constructor(props: any) {
        super(props);
        makeObservable(this);
    }

    @computed get _tableDataIds() {
        return !this.parentViz ? this._props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows);
    }
    // returns all the data records that will be rendered by only returning those records that have been selected by the parent visualization (or all records if there is no parent)
    @computed get _tableData() {
        return !this.parentViz ? this._props.records : this._tableDataIds.map(rowId => this._props.records[rowId]);
    }
    // filters all data to just display selected data if brushed (created from an incoming link)
    @computed get _histogramData() {
        if (this._props.axes.length < 1) return [];
        if (this._props.axes.length < 2) {
            const ax0 = this._props.axes[0];
            if (!/[A-Za-z-:]/.test(this._props.records[0][ax0])) {
                this.numericalXData = true;
            }
            return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]] }));
        }
        const [ax0, ax1] = this._props.axes;
        if (!/[A-Za-z-:]/.test(this._props.records[0][ax0])) {
            this.numericalXData = true;
        }
        if (!/[A-Za-z-:]/.test(this._props.records[0][ax1])) {
            this.numericalYData = true;
        }
        return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]], [ax1]: record[this._props.axes[1]] }));
    }

    @computed get defaultGraphTitle() {
        const [ax0, ax1] = this._props.axes;
        if (this._props.axes.length < 2 || !ax1 || !/\d/.test(this._props.records[0][ax1]) || !this.numericalYData) {
            return ax0 + ' Histogram';
        }
        return ax0 + ' by ' + ax1 + ' Histogram';
    }

    @computed get parentViz() {
        return DocCast(this._props.Document.dataViz_parentViz);
    }

    @computed get rangeVals(): { xMin?: number; xMax?: number; yMin?: number; yMax?: number } {
        if (this.numericalXData) {
            const data = this.data(this._histogramData);
            return { xMin: Math.min.apply(null, data), xMax: Math.max.apply(null, data), yMin: 0, yMax: 0 };
        }
        return { xMin: 0, xMax: 0, yMin: 0, yMax: 0 };
    }

    componentWillUnmount() {
        Array.from(Object.keys(this._disposers)).forEach(key => this._disposers[key]());
    }
    componentDidMount() {
        // restore selected bars
        const svg = this._histogramSvg;
        if (svg) {
            const selectedDataBars = StrListCast(this._props.layoutDoc.dataViz_histogram_selectedData);
            svg.selectAll('rect').attr('class', (d: any) => {
                let selected = false;
                selectedDataBars.forEach(eachSelectedData => {
                    if (d[0] === eachSelectedData) selected = true;
                });
                if (selected) {
                    this.selectedData.push(d);
                    return 'histogram-bar hover';
                }
                return 'histogram-bar';
            });
        }
    }

    // create a document anchor that stores whatever is needed to reconstruct the viewing state (selection,zoom,etc)
    getAnchor = (pinProps?: PinProps) => {
        const anchor = Docs.Create.ConfigDocument({
            title: 'histogram doc selection' + this._currSelected,
        });
        PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document);
        return anchor;
    };

    @computed get height() {
        return this._props.height - this._props.margin.top - this._props.margin.bottom;
    }

    @computed get width() {
        return this._props.width - this._props.margin.left - this._props.margin.right;
    }

    // cleans data by converting numerical data to numbers and taking out empty cells
    data = (dataSet: any) => {
        const validData = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || isNaN(d[key] as any)));
        const field = dataSet[0] ? Object.keys(dataSet[0])[0] : undefined;
        return !field
            ? []
            : validData.map((d: { [x: string]: any }) =>
                  !this.numericalXData //
                      ? d[field]
                      : +d[field!].replace(/\$/g, '').replace(/%/g, '').replace(/</g, '')
              );
    };

    // outlines the bar selected / hovered over
    highlightSelectedBar = (changeSelectedVariables: boolean, svg: any, eachRectWidth: any, pointerX: any, xAxisTitle: any, yAxisTitle: any, histDataSet: any) => {
        let barCounter = -1;
        const selected = svg.selectAll('.histogram-bar').filter((d: any) => {
            barCounter++; // uses the order of bars and width of each bar to find which one the pointer is over
            if (d.length && barCounter * eachRectWidth <= pointerX && pointerX <= (barCounter + 1) * eachRectWidth) {
                let showSelected = this.numericalYData
                    ? this._histogramData.filter((data: { [x: string]: any }) => StrCast(data[xAxisTitle]).replace(/\$/g, '').replace(/%/g, '').replace(/</g, '') == d[0])[0]
                    : histDataSet.filter((data: { [x: string]: any }) => data[xAxisTitle].replace(/\$/g, '').replace(/%/g, '').replace(/</g, '') == d[0])[0];
                if (this.numericalXData) {
                    // calculating frequency
                    if (d[0] && d[1] && d[0] !== d[1]) {
                        showSelected = { [xAxisTitle]: d3.min(d) + ' to ' + d3.max(d), frequency: d.length };
                    } else if (!this.numericalYData) showSelected = { [xAxisTitle]: showSelected[xAxisTitle], frequency: d.length };
                }
                if (changeSelectedVariables) {
                    // for when a bar is selected - not just hovered over
                    let sameAsAny = false;
                    const selectedDataBars = Cast(this._props.layoutDoc.dataViz_histogram_selectedData, listSpec('number'), null);
                    this.selectedData.forEach(eachData => {
                        if (!sameAsAny) {
                            let match = true;
                            Object.keys(d).forEach(key => {
                                if (d[key] !== eachData[key]) match = false;
                            });
                            if (match) {
                                sameAsAny = true;
                                const index = this.selectedData.indexOf(eachData);
                                this.selectedData.splice(index, 1);
                                selectedDataBars.splice(index, 1);
                                this._currSelected = undefined;
                            }
                        }
                    });
                    if (!sameAsAny) {
                        this.selectedData.push(d);
                        selectedDataBars.push(d[0]);
                        this._currSelected = this.selectedData.length > 1 ? undefined : showSelected;
                    }

                    // for filtering child dataviz docs
                    if (this._props.layoutDoc.dataViz_filterSelection) {
                        const selectedRows = Cast(this._props.layoutDoc.dataViz_selectedRows, listSpec('number'), null);
                        this._tableDataIds.forEach(rowID => {
                            let match = false;
                            for (let i = 0; i < d.length; i++) {
                                console.log('Compare: ' + this._props.records[rowID][xAxisTitle].replace(/\$/g, '').replace(/%/g, '').replace(/</g, '') + ' = ' + d[i]);
                                if (this._props.records[rowID][xAxisTitle].replace(/\$/g, '').replace(/%/g, '').replace(/</g, '') == d[i]) match = true;
                            }
                            if (match && !selectedRows?.includes(rowID))
                                selectedRows?.push(rowID); // adding to filtered rows
                            else if (match && sameAsAny) selectedRows.splice(selectedRows.indexOf(rowID), 1); // removing from filtered rows
                        });
                    }
                } else this.hoverOverData = d;
                return true;
            }
            return false;
        });
        if (changeSelectedVariables) {
            if (this._currSelected) this.curBarSelected = selected;
            else this.curBarSelected = undefined;
        }
    };

    // draws the histogram
    drawChart = (dataSet: any, width: number, height: number) => {
        if (dataSet?.length <= 0) return;
        d3.select(this._histogramRef).select('svg').remove();
        d3.select(this._histogramRef).select('.tooltip').remove();

        const data = this.data(dataSet);
        const xAxisTitle = Object.keys(dataSet[0])[0];
        const yAxisTitle = this.numericalYData ? Object.keys(dataSet[0])[1] : 'frequency';
        const uniqueArr: unknown[] = [...new Set(data)];
        let numBins = this.numericalXData && Number.isInteger(data[0]) ? this.rangeVals.xMax! - this.rangeVals.xMin! : uniqueArr.length;
        let translateXAxis = !this.numericalXData || numBins < this.maxBins ? width / (numBins + 1) / 2 : 0;
        if (numBins > this.maxBins) numBins = this.maxBins;
        const startingPoint = this.numericalXData ? this.rangeVals.xMin! : 0;
        const endingPoint = this.numericalXData ? this.rangeVals.xMax! : numBins;

        // converts data into Objects
        let histDataSet = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || isNaN(d[key] as any)));
        if (!this.numericalXData) {
            const histStringDataSet: { [x: string]: unknown }[] = [];
            if (this.numericalYData) {
                for (let i = 0; i < dataSet.length; i++) {
                    histStringDataSet.push({ [yAxisTitle]: dataSet[i][yAxisTitle], [xAxisTitle]: dataSet[i][xAxisTitle] });
                }
            } else {
                for (let i = 0; i < uniqueArr.length; i++) {
                    histStringDataSet.push({ [yAxisTitle]: 0, [xAxisTitle]: uniqueArr[i] });
                }
                for (let i = 0; i < data.length; i++) {
                    const barData = histStringDataSet.filter(each => each[xAxisTitle] == data[i]);
                    histStringDataSet.filter(each => each[xAxisTitle] == data[i])[0][yAxisTitle] = Number(barData[0][yAxisTitle]) + 1;
                }
            }
            histDataSet = histStringDataSet;
        }

        // initial graph and binning data for histogram
        const svg = (this._histogramSvg = d3
            .select(this._histogramRef)
            .append('svg')
            .attr('class', 'graph')
            .attr('width', width + this._props.margin.right + this._props.margin.left)
            .attr('height', height + this._props.margin.top + this._props.margin.bottom)
            .append('g')
            .attr('transform', 'translate(' + this._props.margin.left + ',' + this._props.margin.top + ')'));
        let x = d3
            .scaleLinear()
            .domain(this.numericalXData ? [startingPoint!, endingPoint!] : [0, numBins])
            .range([0, width]);
        const histogram = d3
            .histogram()
            .value(d => d)
            .domain([startingPoint!, endingPoint!])
            .thresholds(x.ticks(numBins));
        const bins = histogram(data);
        let eachRectWidth = width / bins.length;
        const graphStartingPoint = bins[0].x1 && bins[1] ? bins[0].x1! - (bins[1].x1! - bins[1].x0!) : 0;
        bins[0].x0 = graphStartingPoint;
        x = x.domain([graphStartingPoint, endingPoint]).range([0, Number.isInteger(this.rangeVals.xMin!) ? width - eachRectWidth : width]);
        let xAxis;

        // more calculations based on bins
        // x-axis
        if (!this.numericalXData) {
            // reorganize to match data if the data is strings rather than numbers
            // uniqueArr.sort()
            histDataSet.sort();
            for (let i = 0; i < data.length; i++) {
                let index = 0;
                for (let j = 0; j < uniqueArr.length; j++) {
                    if (uniqueArr[j] == data[i]) {
                        index = j;
                    }
                }
                if (bins[index]) bins[index].push(data[i]);
            }
            bins.pop();
            eachRectWidth = width / bins.length;
            bins.forEach(d => {
                d.x0 = d.x0!;
            });
            xAxis = d3
                .axisBottom(x)
                .ticks(bins.length > 1 ? bins.length - 1 : 1)
                .tickFormat(i => uniqueArr[i.valueOf()] as string)
                .tickPadding(10);
            x.range([0, width - eachRectWidth]);
            x.domain([0, bins.length - 1]);
            translateXAxis = eachRectWidth / 2;
        } else {
            let allSame = true;
            for (let i = 0; i < bins.length; i++) {
                if (bins[i] && bins[i][0]) {
                    const compare = bins[i][0];
                    for (let j = 1; j < bins[i].length; j++) {
                        if (bins[i][j] !== compare) allSame = false;
                    }
                }
            }
            if (allSame) {
                translateXAxis = eachRectWidth / 2;
                eachRectWidth = width / bins.length;
            } else {
                eachRectWidth = width / (bins.length + 1);
                const tickDiff = bins.length >= 2 ? bins[bins.length - 2].x1! - bins[bins.length - 2].x0! : 0;
                const curDomain = x.domain();
                x.domain([curDomain[0], curDomain[0] + tickDiff * bins.length]);
            }

            xAxis = d3.axisBottom(x).ticks(bins.length - 1);
            x.range([0, width - eachRectWidth]);
        }
        // y-axis
        const maxFrequency = this.numericalYData ? 
              d3.max(histDataSet, (d: any) => (d[yAxisTitle] ? Number(d[yAxisTitle]!.replace(/\$/g, '')
                .replace(/%/g, '').replace(/</g, '')) : 0)) : 
              d3.max(bins, d => d.length); // prettier-ignore
        const y = d3.scaleLinear().range([height, 0]);
        y.domain([0, +maxFrequency!]);
        const yAxis = d3.axisLeft(y).ticks(maxFrequency!);
        if (this.numericalYData) {
            const yScale = scaleCreatorNumerical(0, Number(maxFrequency), height, 0);
            yAxisCreator(svg.append('g'), width, yScale);
        } else {
            svg.append('g').call(yAxis);
        }
        svg.append('g')
            .attr('transform', 'translate(' + translateXAxis + ', ' + height + ')')
            .call(xAxis);

        // click/hover
        const onPointClick = action((e: any) => this.highlightSelectedBar(true, svg, eachRectWidth, d3.pointer(e)[0], xAxisTitle, yAxisTitle, histDataSet));
        const onHover = action((e: any) => {
            this.highlightSelectedBar(false, svg, eachRectWidth, d3.pointer(e)[0], xAxisTitle, yAxisTitle, histDataSet);
            // eslint-disable-next-line no-use-before-define
            updateHighlights();
        });
        const mouseOut = action(() => {
            this.hoverOverData = undefined;
            // eslint-disable-next-line no-use-before-define
            updateHighlights();
        });
        const updateHighlights = () => {
            const hoverOverBar = this.hoverOverData;
            const { selectedData } = this;
            svg.selectAll('rect').attr('class', (d: any) => {
                let selected = false;
                selectedData.forEach(eachSelectedData => {
                    if (d[0] === eachSelectedData[0]) selected = true;
                });
                return (hoverOverBar && hoverOverBar[0] == d[0]) || selected ? 'histogram-bar hover' : 'histogram-bar';
            });
        };
        svg.on('click', onPointClick).on('mouseover', onHover).on('mouseout', mouseOut);

        // axis titles
        svg.append('text')
            .attr('transform', 'translate(' + width / 2 + ' ,' + (height + 40) + ')')
            .style('text-anchor', 'middle')
            .text(xAxisTitle);
        svg.append('text')
            .attr('transform', 'rotate(-90) translate( 0, ' + -10 + ')')
            .attr('x', -(height / 2))
            .attr('y', -20)
            .style('text-anchor', 'middle')
            .text(yAxisTitle);
        d3.format('.0f');

        // draw bars
        const selected = this.selectedData;
        svg.selectAll('rect')
            .data(bins)
            .enter()
            .append('rect')
            .attr(
                'transform',
                this.numericalYData
                    ? d => {
                          const eachData = histDataSet.filter((hData: { [x: string]: number }) => hData[xAxisTitle] == d[0]);
                          const length = eachData.length ? StrCast(eachData[0][yAxisTitle]).replace(/\$/g, '').replace(/%/g, '').replace(/</g, '') : 0;
                          return 'translate(' + x(d.x0!) + ',' + y(Number(length)) + ')';
                      }
                    : d => 'translate(' + x(d.x0!) + ',' + y(d.length) + ')'
            )
            .attr(
                'height',
                this.numericalYData
                    ? d => {
                          const eachData = histDataSet.filter((hData: { [x: string]: number }) => hData[xAxisTitle] == d[0]);
                          const length = eachData.length ? StrCast(eachData[0][yAxisTitle]).replace(/\$/g, '').replace(/%/g, '').replace(/</g, '') : 0;
                          return height - y(Number(length));
                      }
                    : d => height - y(d.length)
            )
            .attr('width', eachRectWidth)
            .attr('class', selected ? d => (selected && selected[0] == d[0] ? 'histogram-bar hover' : 'histogram-bar') : () => 'histogram-bar')
            .attr('fill', d => {
                let barColor;
                const barColors = StrListCast(this._props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::'));
                barColors.forEach(each => {
                    // eslint-disable-next-line prefer-destructuring
                    if (d[0] && d[0].toString() && each[0] == d[0].toString()) barColor = each[1];
                    else {
                        const range = StrCast(each[0]).split(' to ');
                        // eslint-disable-next-line prefer-destructuring
                        if (Number(range[0]) <= d[0] && d[0] <= Number(range[1])) barColor = each[1];
                    }
                });
                return barColor ? StrCast(barColor) : StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor);
            });
    };

    @action changeSelectedColor = (color: string) => {
        this.curBarSelected.attr('fill', color);
        const barName = StrCast(this._currSelected[this._props.axes[0]].replace(/\$/g, '').replace(/%/g, '').replace(/</g, ''));

        const barColors = Cast(this._props.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null);
        barColors.forEach(each => each.split('::')[0] === barName && barColors.splice(barColors.indexOf(each), 1));
        barColors.push(StrCast(barName + '::' + color));
    };

    @action eraseSelectedColor = () => {
        this.curBarSelected.attr('fill', this._props.layoutDoc.dataViz_histogram_defaultColor);
        const barName = StrCast(this._currSelected[this._props.axes[0]].replace(/\$/g, '').replace(/%/g, '').replace(/</g, ''));

        const barColors = Cast(this._props.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null);
        barColors.forEach(each => each.split('::')[0] === barName && barColors.splice(barColors.indexOf(each), 1));
    };

    // reloads the bar colors and selected bars
    updateSavedUI = () => {
        const svg = this._histogramSvg;
        if (svg) {
            // bar color
            svg.selectAll('rect').attr('fill', (d: any) => {
                let barColor;
                const barColors = StrListCast(this._props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::'));
                barColors.forEach(each => {
                    // eslint-disable-next-line prefer-destructuring
                    if (d[0] && d[0].toString() && each[0] == d[0].toString()) barColor = each[1];
                    else {
                        const range = StrCast(each[0]).split(' to ');
                        // eslint-disable-next-line prefer-destructuring
                        if (Number(range[0]) <= d[0] && d[0] <= Number(range[1])) barColor = each[1];
                    }
                });
                return barColor ? StrCast(barColor) : StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor);
            });
        }
    };

    render() {
        this.updateSavedUI();
        this._histogramData;
        let curSelectedBarName = '';
        let titleAccessor: any = 'dataViz_histogram_title';
        if (this._props.axes.length === 2) titleAccessor = titleAccessor + this._props.axes[0] + '-' + this._props.axes[1];
        else if (this._props.axes.length > 0) titleAccessor += this._props.axes[0];
        if (!this._props.layoutDoc[titleAccessor]) this._props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
        if (!this._props.layoutDoc.dataViz_histogram_defaultColor) this._props.layoutDoc.dataViz_histogram_defaultColor = '#69b3a2';
        if (!this._props.layoutDoc.dataViz_histogram_barColors) this._props.layoutDoc.dataViz_histogram_barColors = new List<string>();
        if (!this._props.layoutDoc.dataViz_histogram_selectedData) this._props.layoutDoc.dataViz_histogram_selectedData = new List<string>();
        let selected = 'none';
        if (this._currSelected) {
            curSelectedBarName = StrCast(this._currSelected![this._props.axes[0]].replace(/\$/g, '').replace(/%/g, '').replace(/</g, ''));
            selected = '{ ';
            Object.keys(this._currSelected).forEach(key => {
                key //
                    ? (selected += key + ': ' + this._currSelected[key] + ', ')
                    : '';
            });
            selected = selected.substring(0, selected.length - 2) + ' }';
            if (this._props.titleCol !== '' && (!this._currSelected.frequency || this._currSelected.frequency < 10)) {
                selected += '\n' + this._props.titleCol + ': ';
                this._tableData.forEach(each => {
                    if (this._currSelected[this._props.axes[0]] === each[this._props.axes[0]]) {
                        if (this._props.axes[1]) {
                            if (this._currSelected[this._props.axes[1]] === each[this._props.axes[1]]) selected += each[this._props.titleCol] + ', ';
                        } else selected += each[this._props.titleCol] + ', ';
                    }
                });
                selected = selected.slice(0, -1).slice(0, -1);
            }
        }
        let selectedBarColor;
        const barColors = StrListCast(this._props.layoutDoc.histogramBarColors).map(each => each.split('::'));
        barColors.forEach(each => {
            // eslint-disable-next-line prefer-destructuring
            each[0] === curSelectedBarName && (selectedBarColor = each[1]);
        });

        if (this._histogramData.length > 0 || !this.parentViz) {
            return this._props.axes.length >= 1 ? (
                <div className="chart-container" style={{ width: this._props.width + this._props.margin.right }}>
                    <div className="graph-title">
                        <EditableText
                            val={StrCast(this._props.layoutDoc[titleAccessor])}
                            setVal={undoable(
                                action(val => {
                                    this._props.layoutDoc[titleAccessor] = val as string;
                                }),
                                'Change Graph Title'
                            )}
                            color="black"
                            size={Size.LARGE}
                            fillWidth
                        />
                        &nbsp; &nbsp;
                        <ColorPicker
                            tooltip="Change Default Bar Color"
                            type={Type.SEC}
                            icon={<FaFillDrip />}
                            selectedColor={StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor)}
                            setFinalColor={undoable(color => {
                                this._props.layoutDoc.dataViz_histogram_defaultColor = color;
                            }, 'Change Default Bar Color')}
                            setSelectedColor={undoable(color => {
                                this._props.layoutDoc.dataViz_histogram_defaultColor = color;
                            }, 'Change Default Bar Color')}
                            size={Size.XSMALL}
                        />
                    </div>
                    <div
                        ref={r => {
                            this._histogramRef = r;
                            r && this.drawChart(this._histogramData, this.width, this.height);
                        }}
                    />
                    {selected !== 'none' ? (
                        <div className="selected-data">
                            Selected: {selected}
                            &nbsp; &nbsp;
                            <ColorPicker
                                tooltip="Change Bar Color"
                                type={Type.SEC}
                                icon={<FaFillDrip />}
                                selectedColor={selectedBarColor || this.curBarSelected.attr('fill')}
                                setFinalColor={undoable(color => this.changeSelectedColor(color), 'Change Selected Bar Color')}
                                setSelectedColor={undoable(color => this.changeSelectedColor(color), 'Change Selected Bar Color')}
                                size={Size.XSMALL}
                            />
                            &nbsp;
                            <IconButton
                                icon={<FontAwesomeIcon icon="eraser" />}
                                size={Size.XSMALL}
                                color="black"
                                type={Type.SEC}
                                tooltip="Revert to the default bar color" //
                                onClick={undoable(this.eraseSelectedColor, 'Change Selected Bar Color')}
                            />
                        </div>
                    ) : null}
                </div>
            ) : (
                <span className="chart-container"> first use table view to select a column to graph</span>
            );
        }
        // when it is a brushed table and the incoming table doesn't have any rows selected
        return <div className="chart-container">Selected rows of data from the incoming DataVizBox to display.</div>;
    }
}
