/// <reference types="mathjs" />
/**
 * Introduction
 * Bar chart sparlines are a collection of rectangles, a.k.a. bars, drawn
 * alongside the canvas x-axis, with a small gap between them.
 *
 * Bar chart sparlines are charactized by their types: positive, negative,
 * dual, and tri. Positive charts' bars with positve heights are drawn
 * northward; bars with negative heights are cropped out. Negative charts'
 * bars with negative heights are drawn southward; bars with positive heights
 * are cropped out. Dual charts' bars heights are negative, zero, or positive,
 * with a positive height bars drawn northward and negative ones southward.
 * Tri charts have equal height bars, with positive drawn northward, zero
 * straddling the x-axis, and negative southward.

 * Bars are characterized by origin, height, width, gap, and fill color. The
 * origin is always (0,0). The height is provided, and scaled to fit within the
 * canvas. The width is calculated and its proportional number of bars and the
 * the canvas width. The gap is provided. The fill color is provided and used to
 * draw the bars' backgrounds.
 *
 * Calculation parameters
 * The parameters required to draw a bar char sparkline fall within two
 * categories: attributes, calculated. See below for their definitions and
 * descriptions.
 *
 * Bar width calculation
 * The bar width, barWidth, is the ratio between the canvas width and the
 * number of bars to draw, rounded down. The barWidth calculation is an
 * iteration seeking the number o bars to draw, barHeights.length, that yields
 * a barWidth equal or higher than the minimum bar width, minimumBarWidth. If
 * the initial barWidth, Math.floor(canvas.width / heights.length), yields a
 * barWidth that is less than minimumBarWidth, we drop the leftmost barHeights
 * element and recalculate the barWidth using the new heights.length; we
 * iterate until the barWidth is greater or equal to minBarWidth.
 *
 * Bar gap insertion
 * The bar gaps, barGap, inserted between the bars might cause rightmost bars to
 * be cropped. The barGap insertion is an iteration seeking for a
 * barHeights.length enabling barGaps to be inserted without cropping any
 * rightmost bars. It has two phases: reducing the barWidth and pruning
 * barHeights leftmost elements.
 *
 * If the initial width required, widthRequired, to insert the
 * bars and their gaps,
 * barWidth*barHeights.length + barGap*(barHeights.length - 1), is greater than
 * the canvas.width and the barWidth is greater than the minimumBarWidth,
 * decrement the barWidth by one pixel and recalculate
 * the widthRequired using the new barWidth; we iterate until the
 * widthRequired is less or equal to canvas.width.
 *
 * If the initial width required, widthRequired, to insert the
 * bars and their gaps,
 * barWidth*barHeights.length + barGap*(barHeights.length - 1), is greater than
 * the canvas.width and the barWidth is not greater than the minimumBarWidth, we
 * drop the leftmost barHeights element and recalculate the widthRequired using
 * the new heights.length; we iterate until the widthRequired is less or equal to
 * canvas.width.
 *
 0        1         2         3         4         5         6         7         8
 12345678901234567890123456789012345678901234567890123456789012345678901234567890
 * Bar chart type drawing
 * The bar chart origin, direction, and scale calculations depend on the bar
 * chart type. We use the canvas setTransform and translate functions to aid in
 * setting them. We start by establishing the canvas default state and then
 * describe the operations to transform it to suit the bar char we are drawing
 *
 * In the canvas original state, its origin is top-let, positive drawing
 * southward, and negative northward. The canvas translate method is used to
 * move the origin; the canvas scale method is used to flip the canvas drawing
 * and to move the origin when inserting gaps.
 *
 * Wehn drawing a positive chart:
 * - the canvas origin is translated to the bottom-left
 * - the drawing is scaled to
 *   - flip the drawing direction
 *   - fit the barHeights into the canvas height.
 *
 * Wehn drawing a negative chart:
 *  - the canvas origin remains at top-right
 * - the drawing is scaled to
 *   - flip the drawing direction
 *   - fit the barHeights into the canvas height.
 *
 * Wehn drawing a dual chart:
 *  - the canvas origin is translated to the middle-left
 * - the drawing is scaled to
 *   - flip the drawing direction
 *   - fit the barHeights into half of the canvas height.
 *
 * Wehn drawing a tri chart:
 *  - the canvas origin is translated to the middle-left
 * - the drawing is scaled to
 *   - flip the drawing direction
 *   - fit the barHeights into half of the canvas height.
 *   - All bars are drawn with height = canvas.height / 2
 *   - zero heights are drawn half northward, and hald southward
 *
 *   TODO: Add validation for color names ... ValidColors.ts
 */
import { Bar } from './bar';
import { Bar3d } from './bar-3d';
import { Matrix } from 'mathjs';
import { Rectangle } from './rectangle';
export declare class BarChart {
    canvasEl: HTMLCanvasElement;
    chartType: string;
    barHeights: number[];
    minimumBarWidth: number;
    barGap: number;
    fillColorMinus: string;
    fillColorZero: string;
    fillColorPlus: string;
    ctx: CanvasRenderingContext2D;
    canvasWidth: number;
    canvasHeight: number;
    barWidth: number;
    bars: Bar[];
    bars_3d: Bar3d[];
    coordinatesTips: any;
    VALID_TYPES: string[];
    POSITIVE: number;
    NEGATIVE: number;
    DUAL: number;
    TRI: number;
    tooltipId: string;
    private cssColorString;
    setCanvasEl(value: HTMLCanvasElement): void;
    getCanvasEl(): HTMLCanvasElement;
    setChartType(value: string): void;
    getChartType(): string;
    setBarHeights(value: number[]): void;
    getBarHeights(): number[];
    setMinimumBarWidth(value: number): void;
    getMinimumBarWidth(): number;
    setBarGap(value: number): void;
    getBarGap(): number;
    setFillColorMinus(value: string): void;
    getFillColorMinus(): string;
    setFillColorZero(value: string): void;
    getFillColorZero(): string;
    setFillColorPlus(value: string): void;
    getFillColorPlus(): string;
    setCtx(value: CanvasRenderingContext2D): void;
    getCtx(): CanvasRenderingContext2D;
    setCanvasWidth(value: number): void;
    getCanvasWidth(): number;
    setCanvasHeight(value: number): void;
    getCanvasHeight(): number;
    setBarWidth(value: number): void;
    getBarWidth(): number;
    getBars(): Bar[];
    setBars3D(value: Bar3d[]): void;
    getBars3D(): Bar3d[];
    setCoordinatesTips(value: Rectangle[]): void;
    getCoordinatesTips(): Rectangle[];
    constructor(canvasEl: HTMLCanvasElement, chartType: string, barHeights: number[], minimumBarWidth: number, barGap: number, fillColorMinus: string, fillColorZero: string, fillColorPlus: string);
    draw(): void;
    /**
     * The bar width, barWidth, is the ratio between the canvas width and the
     * number of bars to draw, rounded down. The barWidth calculation is an
     * iteration seeking the number o bars to draw, barHeights.length, that yields
     * a barWidth equal or higher than the minimum bar width, minimumBarWidth. If
     * the initial barWidth, Math.floor(canvas.width / heights.length), yields a
     * barWidth that is less than minimumBarWidth, we drop the leftmost barHeights
     * element and recalculate the barWidth using the new heights.length; we iterate
     * until the barWidth is greater or equal to minBarWidth.
     *
     * Ideally, all bars will fit in the canvas.width, when drawn with the
     * minBarWidth. Therefore, if maximum number of bars that can be drawn in the
     * canvas is equal of larger than the number of bars to be drawn, we are done.
     * Otherwise, if barHeights has more bars than can be draw and must be pruned
     * to the maximum number of bars that can be drawn in the canvas.
     *
     * maxNumberOfBarsThatCanBeDrawnOnCanvas = Math.floor(canvasWidth / minBarWidth)
     *
     * @param {number} canvasWidth
     * @param {number[]} barHeights
     * @param {number} minBarWidth
     * @returns {number[]}
     */
    calculateBarWidth(canvasWidth: number, barHeights: number[], minBarWidth: number): number[];
    computeBarWidth(canvasWidth: number, barHeights: number[]): number;
    /**
     * If the initial width required, widthRequired, to insert the
     * bars and their gaps,
     * barWidth*barHeights.length + barGap*(barHeights.length - 1), is greater than
     * the canvas.width and the barWidth is greater than the minimumBarWidth,
     * decrement the barWidth by one pixel and recalculate
     * the widthRequired using the new barWidth; we iterate until the
     * widthRequired is less or equal to canvas.width.
     *
     *
     * In essence, The iteration seeks to find the barWidth that solves the
     * following equation:
     * canvas.width <= barWidth * barHeights.length + barGap * (barHeights.length - 1)
     *
     * Resolving for barWidth.length, we get:
     * barWidth = Math.max(minimumBarWidth, Math.floor(canvas.width + barGap - barGap * barHeights.length) /barHeights.length))
     *
     * barWidth = Math.max(minimumBarWidth, Math.floor( (canvasWidth - (barGap * (barHeights.length - 1))) / barHeights.length));
     *
     *
     * @param {number} canvasWidth
     * @param {number[]} barHeights
     * @param {number} barGap
     * @param {number} minimumBarWidth
     * @returns {number}
     */
    insertGapsUsingBarWidth(canvasWidth: number, barHeights: number[], barGap: number, minimumBarWidth: number): number;
    /**
     * If the initial width required, widthRequired, to insert the
     * bars and their gaps,
     * barWidth*barHeights.length + barGap*(barHeights.length - 1), is greater than
     * the canvas.width and the barWidth is not greater than the minimumBarWidth, we
     * drop the leftmost barHeights element and recalculate the widthRequired using
     * the new heights.length; we iterate until the widthRequired is less or equal to
     * canvas.width.
     *
     * In essence, The iteration seeks to find the barHeights.length that solves the
     * following equation:
     * canvas.width <= barHeights.length * barWidth + (barHeights.length - 1) * barGap
     *
     * Resolving for barHeights.length, we get:
     * barHeights.length = Math.floor((canvas.width + barGap) / (barWidth + barGap))
     *
     * Given the desired barHeights.length, we prune barHeights to have the desired
     * length
     *
     * @param {number} canvasWidth
     * @param {number[]} barHeights
     * @param {number} barWidth
     * @param {number} barGap
     * @returns {number[]}
     */
    insertGapsUsingBarHeights(canvasWidth: number, barHeights: number[], barWidth: number, barGap: number): number[];
    buildBars(canvasHeight: number, barHeights: number[], barWidth: number, chartType: string, fillColorMinus: string, fillColorZero: string, fillColorPlus: string): Bar[];
    buildBars_1(barGap: number, barHeights: number[], barWidth: number, chartType: string, fillColorMinus: string, fillColorZero: string, fillColorPlus: string): Bar3d[];
    /**
     * Builds a collection of Bar3D bars, one for each barHeight
     * @param barGap
     * @param barHeights
     * @param barWidth
     * @param chartType
     * @param fillColorMinus
     * @param fillColorPlus
     * @param fillColorZero
     */
    buildWorldCoordinateBars(barGap: number, barHeights: number[], barWidth: number, chartType: string, fillColorMinus: string, fillColorPlus: string, fillColorZero: string): Bar3d[];
    /**
     * Scale the Y coordinates; note that the X coordinates were scaled during the calculations to establish the width and gap.
     * TODO: examine the possibility to switch all calculation to be done AFTER all transformations are done.
     * @param barHeights
     * @param chartType
     * @param canvasHeight
     */
    scaleToCanvasHeight(barHeights: number[], chartType: string, canvasHeight: number): Matrix;
    /**
     * Calculate sFlipCanvasMatrix, to switch from world coordinates to canvas coordinates
     */
    scaleToCanvasCoordinates(): Matrix;
    moveWithinCanvas(canvasHeight: number, chartType: string): Matrix;
    buildCoordinateTips(bard3D: Bar3d[]): Rectangle[];
    _draw_1(ctx: CanvasRenderingContext2D, bars: Bar3d[]): void;
    /**
     * Sparkline Barchart Mouse Move Handler
     * @param $event
     * @param canvasEl
     */
    handleMouseMove($event: MouseEvent, canvasEl: HTMLElement): void;
    handleMouseOut(): void;
}
