"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AdaptableWizard = exports.useWizardContext = exports.AdaptableWizardContext = void 0;
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const WizardLegend_1 = require("./WizardLegend");
const ArrayExtensions_1 = require("../../Utilities/Extensions/ArrayExtensions");
const rebass_1 = require("rebass");
const Dialog_1 = tslib_1.__importDefault(require("../../components/Dialog"));
const SimpleButton_1 = tslib_1.__importDefault(require("../../components/SimpleButton"));
const Panel_1 = tslib_1.__importDefault(require("../../components/Panel"));
const kebabCase_1 = tslib_1.__importDefault(require("lodash/kebabCase"));
exports.AdaptableWizardContext = React.createContext({
    data: null,
    updateGoBackState: () => { },
    onRender: (ActiveStep) => { },
    api: null,
});
const useWizardContext = () => {
    return React.useContext(exports.AdaptableWizardContext);
};
exports.useWizardContext = useWizardContext;
class DummyActiveStep {
    canNext() {
        return false;
    }
    canBack() {
        return false;
    }
    next() {
        // no implementation for this
    }
    back() {
        // no implementation for this
    }
    getIndexStepIncrement() {
        return 1;
    }
    getIndexStepDecrement() {
        return 1;
    }
}
//Remark : the component doesnt handle the change of props once displayed... It's easy to do but not sure it's needed
//as in the top component we do the render with a ternary expression so we add/remove the element from the render instead of having a property
//Show/hide.
class AdaptableWizard extends React.Component {
    constructor(props) {
        super(props);
        //we need to init with a dummy one as Ref is a callback once the component is rendered. So once set we force Re render....
        //I have no idea so far how to do it differently
        this.ActiveStep = new DummyActiveStep();
        let indexStart = 0;
        if (this.props.stepStartIndex) {
            indexStart = this.props.stepStartIndex;
        }
        let BodyElement = this.props.steps[indexStart].Element;
        this.stepName = this.props.steps[indexStart].StepName;
        let newElement = this.cloneWizardStep(BodyElement);
        this.state = { ActiveState: newElement, IndexState: indexStart };
    }
    render() {
        let wizardStepNames = ArrayExtensions_1.ArrayExtensions.RetrieveDistinct(this.props.steps.map((x) => {
            return x.StepName;
        }));
        const hasNext = this.props.steps.length > 1;
        const hasBack = hasNext;
        return (React.createElement(exports.AdaptableWizardContext.Provider, { value: {
                data: this.props.data,
                updateGoBackState: () => this.ForceUpdateGoBackState(),
                api: this.props.api,
                onRender: (ActiveStep) => {
                    this.ActiveStep = ActiveStep;
                    this.forceUpdate();
                },
            } },
            React.createElement(Dialog_1.default, { modal: true, isOpen: true, showCloseButton: false, onDismiss: () => (this.props.onHide ? this.props.onHide() : null) },
                React.createElement(rebass_1.Flex, { flexDirection: "column", "data-name": this.props.moduleInfo.FriendlyName
                        ? `${(0, kebabCase_1.default)(this.props.moduleInfo.FriendlyName)}-wizard`
                        : '', style: {
                        height: '100%',
                        width: '70vw',
                        maxWidth: 1000,
                        maxHeight: '80vh',
                        ...this.props.style,
                    } },
                    React.createElement(Panel_1.default, { header: this.props.moduleInfo.FriendlyName, border: "none", className: "ab-WizardDialog__steps", borderRadius: "none", variant: "primary", style: { flex: 'none' } }, this.props.showStepsLegend === false ? null : (React.createElement(WizardLegend_1.WizardLegend, { StepNames: wizardStepNames, ActiveStepName: this.stepName, FriendlyName: '', CanShowAllSteps: this.canFinishWizard(), onStepButtonClicked: (s) => this.onStepButtonClicked(s) }))),
                    React.createElement(rebass_1.Flex, { style: { flex: 1, overflow: 'auto' }, flexDirection: "column" }, this.state.ActiveState),
                    React.createElement(rebass_1.Flex, { flexDirection: "row", padding: 2, backgroundColor: "primary", alignItems: "center", className: "ab-WizardDialog__footer" },
                        React.createElement(SimpleButton_1.default, { tone: "neutral", variant: "text", "data-name": "close", onClick: () => this.props.onHide(), tooltip: this.props.closeTooltip ?? 'Close wizard', accessLevel: 'Full' }, this.props.closeText ?? 'CLOSE'),
                        React.createElement("div", { style: { flex: 1 } }),
                        hasBack ? (React.createElement(SimpleButton_1.default, { "data-name": "back", variant: "outlined", disabled: !this.ActiveStep.canBack() || this.isFirstStep(), onClick: () => this.handleClickBack(), icon: "arrow-left", accessLevel: 'Full' }, "Back")) : null,
                        hasNext ? (React.createElement(SimpleButton_1.default, { variant: "outlined", "data-name": "next", disabled: !this.ActiveStep.canNext() || this.isLastStep(), onClick: () => this.handleClickNext(), icon: "arrow-right", iconPosition: "end", accessLevel: 'Full', marginLeft: 2, marginRight: 2 }, "Next")) : null,
                        React.createElement(SimpleButton_1.default, { tone: "accent", "data-name": "finish", variant: "raised", disabled: !this.canFinishWizard(), onClick: () => this.handleClickFinish(), icon: 'check', accessLevel: 'Full' }, "Finish"))))));
    }
    onStepButtonClicked(stepName) {
        let wizardStepInfo = this.props.steps.find((s) => s.StepName == stepName);
        let bodyElement = wizardStepInfo.Element;
        let newElement = this.cloneWizardStep(bodyElement);
        this.stepName = wizardStepInfo.StepName;
        this.setState({
            ActiveState: newElement,
            IndexState: wizardStepInfo.Index,
        });
    }
    ForceUpdateGoBackState() {
        this.forceUpdate();
    }
    isLastStep() {
        return this.state.IndexState == this.props.steps.length - 1;
    }
    isFirstStep() {
        return this.state.IndexState == 0;
    }
    canFinishWizard() {
        return this.ActiveStep.canNext() && this.props.canFinishWizard();
    }
    handleClickBack() {
        if (!this.isFirstStep()) {
            if (this.ActiveStep.canBack()) {
                let decrement = this.ActiveStep.getIndexStepDecrement();
                this.ActiveStep.back();
                let activeWizardInfo = this.props.steps[this.state.IndexState - decrement];
                let bodyElement = activeWizardInfo.Element;
                let newElement = this.cloneWizardStep(bodyElement);
                this.stepName = activeWizardInfo.StepName;
                this.setState({
                    ActiveState: newElement,
                    IndexState: this.state.IndexState - decrement,
                });
            }
        }
    }
    handleClickNext() {
        if (this.ActiveStep.canNext()) {
            let increment = this.ActiveStep.getIndexStepIncrement();
            this.ActiveStep.next();
            let activeWizardInfo = this.props.steps[this.state.IndexState + increment];
            let bodyElement = activeWizardInfo.Element;
            let newElement = this.cloneWizardStep(bodyElement);
            this.stepName = activeWizardInfo.StepName;
            this.setState({
                ActiveState: newElement,
                IndexState: this.state.IndexState + increment,
            });
        }
    }
    handleClickFinish() {
        if (this.ActiveStep.canNext()) {
            this.ActiveStep.next();
            if (this.props.onFinish) {
                this.props.onFinish();
            }
            this.props.onHide();
        }
    }
    //So we inject everything needed for the Wizard
    cloneWizardStep(step) {
        return React.cloneElement(step, {
            ref: (Element) => {
                if (Element) {
                    this.ActiveStep = Element;
                    this.forceUpdate();
                }
                else {
                    this.ActiveStep = null;
                }
            },
            data: this.props.data,
            updateGoBackState: () => this.ForceUpdateGoBackState(),
            api: this.props.api,
        });
    }
}
exports.AdaptableWizard = AdaptableWizard;
