import * as React from 'react';
import { delegateCombine, delegateRemove, TypeRegistrar } from "igniteui-react-core";
import { isValidProp, getModifiedProps, toPoint, ensureBool, NamePatcher } from "igniteui-react-core";
import { IgrStackedSeriesCreatedEventArgs } from './igr-stacked-series-created-event-args';
import { IgrCategorySeries } from './igr-category-series';
import { NotifyCollectionChangedAction } from "igniteui-react-core";
import { CollectionAdapter } from "igniteui-react-core";
import { ContentChildrenManager } from "igniteui-react-core";
import { IgrStackedSeriesCollection } from './igr-stacked-series-collection';
/**
 * Represents a base class for stacked series.
*/
export class IgrStackedSeriesBase extends IgrCategorySeries {
    createImplementation() {
        return null;
    }
    get i() {
        return this._implementation;
    }
    constructor(props) {
        super(props);
        /**
         * The series actually present in the chart. Do not directly modify this array.
         * This array's contents can be modified by causing React to reproject the child content.
         * Or adding and removing series from the manual series collection on the series property.
         */
        this.actualSeries = [];
        this.contentSeries = [];
        this._series = null;
        this._seriesAdapter = null;
        this._seriesCreated = null;
        this._seriesCreated_wrapped = null;
        if (this._styling) {
            NamePatcher.ensureStylablePatched(Object.getPrototypeOf(this));
        }
        this._seriesAdapter = new CollectionAdapter(this.contentSeries, this.i.series, this.actualSeries, (c) => c.i, (i) => {
            i.owner = this;
            i.provideRenderer(this._renderer);
            // i.provideData(this._dataSource);
            // i.bindAxes(this.actualAxes);
            // this._ensureDefaultTooltip(i);
            // this._ensureTooltipCreated(i);
        }, (i) => {
            i.provideRenderer(null);
            // i.provideData(null); 
        });
        this._contentChildrenManager = new ContentChildrenManager((ch) => ch.key || ch.props.name, (ch) => ch.key || ch.props.name, () => this._updateContentChildren());
    }
    initializeProperties() {
        for (const p of Object.keys(this.props)) {
            if (isValidProp(this, p)) {
                this[p] = this.props[p];
            }
        }
    }
    componentDidMount() {
        this.initializeProperties();
    }
    shouldComponentUpdate(nextProps, nextState) {
        const mod = getModifiedProps(this.props, nextProps);
        for (const p of Object.keys(mod)) {
            if (isValidProp(this, p)) {
                this[p] = mod[p];
            }
        }
        return true;
    }
    render() {
        let children = this._contentChildrenManager.getChildren(this.props.children);
        let div = React.createElement("div", {
            children: children
        });
        return div;
    }
    static _createFromInternal(internal) {
        if (!internal) {
            return null;
        }
        if (!internal.$type) {
            return null;
        }
        let name = internal.$type.name;
        let externalName = "Igr" + name;
        if (!TypeRegistrar.isRegistered(externalName)) {
            return null;
        }
        return TypeRegistrar.create(externalName);
    }
    _updateContentChildren() {
        this.contentSeries.length = 0;
        let contentChildrenActual = this._contentChildrenManager.contentChildrenActual;
        for (let i = 0; i < contentChildrenActual.length; i++) {
            this.contentSeries.push(contentChildrenActual[i]);
        }
        if (this._seriesAdapter !== null) {
            this._seriesAdapter.notifyContentChanged();
        }
    }
    /**
     * A collection or manually added series for the chart.
    */
    get series() {
        if (this._series === null) {
            let coll = new IgrStackedSeriesCollection();
            let inner = coll._innerColl;
            inner.addListener((sender, e) => {
                switch (e.action) {
                    case NotifyCollectionChangedAction.Add:
                        this._seriesAdapter.insertManualItem(e.newStartingIndex, e.newItems.item(0));
                        break;
                    case NotifyCollectionChangedAction.Remove:
                        this._seriesAdapter.removeManualItemAt(e.oldStartingIndex);
                        break;
                    case NotifyCollectionChangedAction.Replace:
                        this._seriesAdapter.removeManualItemAt(e.oldStartingIndex);
                        this._seriesAdapter.insertManualItem(e.newStartingIndex, e.newItems.item(0));
                        break;
                    case NotifyCollectionChangedAction.Reset:
                        this._seriesAdapter.clearManualItems();
                        break;
                }
            });
            this._series = coll;
        }
        return this._series;
    }
    _provideRenderer(renderer) {
        this._renderer = renderer;
        if (this.actualSeries != null) {
            for (let i = 0; i < this.actualSeries.length; i++) {
                this.actualSeries[i].provideRenderer(renderer);
            }
        }
    }
    /**
 * Gets or sets whether series should be automatically generated. Reqiures the use of GroupBy as the ItemsSource.
*/
    get autoGenerateSeries() {
        return this.i.xo;
    }
    set autoGenerateSeries(v) {
        this.i.xo = ensureBool(v);
    }
    /**
     * Gets or sets whether the order of the fragment series should be reversed in the legend.
    */
    get reverseLegendOrder() {
        return this.i.xq;
    }
    set reverseLegendOrder(v) {
        this.i.xq = ensureBool(v);
    }
    /**
     * Checks if this series is a stacked series
    */
    get isStacked() {
        return this.i.isStacked;
    }
    get isPercentBased() {
        return this.i.xp;
    }
    findByName(name) {
        var baseResult = super.findByName(name);
        if (baseResult) {
            return baseResult;
        }
        if (this.series != null && this.series.findByName && this.series.findByName(name)) {
            return this.series.findByName(name);
        }
        return null;
    }
    /**
 * Called to notify about changes to indexed-based properties, e.g. Brushes, Outlines, MarkerBrushes, MarkerOutlines and refresh series

*/
    notifyIndexedPropertiesChanged() {
        this.i.oh();
    }
    /**
     * Simulates a pointer hover over the series surface.
    
    * @param point  * The pointer position relative to the series viewport over which to hover.
    */
    simulateHover(point) {
        this.i.p4(toPoint(point));
    }
    /**
     * Scrolls the series to display the item for the specified data item.
     * The series is scrolled by the minimum amount required to place the specified data item within
     * the central 80% of the visible axis.
    
    * @param item  * The data item (item) to scroll to.
    */
    scrollIntoView(item) {
        let iv = this.i.fp(item);
        return (iv);
    }
    replayTransitionIn() {
        this.i.pv();
    }
    /**
     * Event raised when a new fragment series is automatically generated.
    */
    get seriesCreated() {
        return this._seriesCreated;
    }
    set seriesCreated(ev) {
        if (this._seriesCreated_wrapped !== null) {
            this.i.seriesCreated = delegateRemove(this.i.seriesCreated, this._seriesCreated_wrapped);
            this._seriesCreated_wrapped = null;
            this._seriesCreated = null;
        }
        this._seriesCreated = ev;
        this._seriesCreated_wrapped = (o, e) => {
            let outerArgs = new IgrStackedSeriesCreatedEventArgs();
            outerArgs._provideImplementation(e);
            if (this.beforeSeriesCreated) {
                this.beforeSeriesCreated(this, outerArgs);
            }
            if (this._seriesCreated) {
                this._seriesCreated(this, outerArgs);
            }
        };
        this.i.seriesCreated = delegateCombine(this.i.seriesCreated, this._seriesCreated_wrapped);
        ;
    }
}
