"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UIToggle = exports.UIToggleSize = void 0;
const react_1 = __importDefault(require("react"));
const react_dom_1 = __importDefault(require("react-dom"));
const react_2 = require("@fluentui/react");
const ValidationMessage_1 = require("../../helper/ValidationMessage");
const UIIcon_1 = require("../UIIcon");
const Icons_1 = require("../Icons");
var UIToggleSize;
(function (UIToggleSize) {
    UIToggleSize["Standard"] = "Standard";
    UIToggleSize["Small"] = "Small";
})(UIToggleSize || (exports.UIToggleSize = UIToggleSize = {}));
const TOGGLE_SIZE = {
    width: 30,
    height: 18,
    padding: '0 1px',
    margin: '0',
    label: {
        fontSize: 13,
        padding: '0px 0px 1px 0px'
    },
    circle: {
        width: 14,
        height: 14,
        borderWidth: 1
    }
};
const ICON_STYLE = { display: 'flex' };
const DISABLED_OPACITY = 0.4;
const COLORS = {
    pill: {
        unchecked: {
            background: 'var(--vscode-editorWidget-background)',
            borderColor: 'var(--vscode-editorWidget-border)',
            hover: {
                background: 'var(--vscode-editorWidget-background)',
                borderColor: 'var(--vscode-editorWidget-border)'
            }
        },
        checked: {
            background: 'var(--vscode-editorWidget-background)',
            borderColor: 'var(--vscode-contrastActiveBorder, var(--vscode-editorWidget-border))',
            hover: {
                background: 'var(--vscode-editorWidget-background)',
                borderColor: 'var(--vscode-contrastActiveBorder, var(--vscode-editorWidget-border))'
            }
        },
        focus: {
            outline: '1px solid var(--vscode-focusBorder) !important'
        }
    },
    thumb: {
        unchecked: {
            background: 'var(--vscode-button-secondaryBackground)',
            borderColor: 'var(--vscode-button-border, transparent)',
            hover: {
                borderColor: 'var(--vscode-button-border, transparent)',
                background: 'var(--vscode-contrastBorder, var(--vscode-button-secondaryHoverBackground))'
            }
        },
        checked: {
            background: 'var(--vscode-button-background)',
            borderColor: 'var(--vscode-contrastActiveBorder, var(--vscode-button-border, transparent))',
            hover: {
                borderColor: 'var(--vscode-contrastActiveBorder, var(--vscode-button-border, transparent))',
                background: 'var(--vscode-contrastActiveBorder, var(--vscode-button-hoverBackground))'
            }
        }
    }
};
/**
 * UIToggle component.
 * based on https://developer.microsoft.com/en-us/fluentui#/controls/web/toggle
 *
 * @exports
 * @class UIToggle
 * @extends {React.Component<IToggleProps, {}>}
 */
class UIToggle extends react_1.default.Component {
    /**
     * Initializes component properties.
     *
     * @param {UIToggleProps} props
     */
    constructor(props) {
        super(props);
        this.toggleRootRef = react_1.default.createRef();
        this.handleChange = this.handleChange.bind(this);
        this.replaceThumbWithIcon = this.replaceThumbWithIcon.bind(this);
    }
    /**
     * Lifecycle method called immediately after a component is mounted.
     * Executes initialization logic such as DOM manipulations or fetching data.
     *
     * @returns {void} This method does not return a value.
     */
    componentDidMount() {
        this.replaceThumbWithIcon(this.props.checked ?? this.props.defaultChecked);
    }
    /**
     * Determines whether the component should update when the new props are received.
     * This method is typically used for performance optimization.
     *
     * @param {UIToggleProps} nextProps - The next props to be received by the component.
     * @returns {boolean} A boolean value indicating whether the component should update.
     */
    shouldComponentUpdate(nextProps) {
        if (nextProps.checked !== this.props.checked) {
            this.replaceThumbWithIcon(nextProps.checked);
        }
        return true;
    }
    /**
     * Handles the change event triggered by the user interaction.
     *
     * @param {React.MouseEvent<HTMLElement>} event - The mouse event object associated with the interaction.
     * @param {boolean} [checked] - An optional parameter indicating the current state of the interaction.
     * @returns {void} This method does not return a value.
     */
    handleChange(event, checked) {
        this.replaceThumbWithIcon(checked);
        this.props.onChange?.(event, checked);
    }
    /**
     * Replaces the thumb element of a toggle switch with an icon based on the toggle's state.
     *
     * @param {boolean} [checked] Optional. Represents the state of the toggle switch. If not provided, it checks `defaultChecked` prop or defaults to `false`.
     * @returns {void} Does not return a value.
     */
    replaceThumbWithIcon(checked = false) {
        if (this.toggleRootRef.current) {
            const thumbElement = this.toggleRootRef.current?.querySelector('.ms-Toggle-thumb');
            if (thumbElement) {
                react_dom_1.default.render(react_1.default.createElement(UIIcon_1.UIIcon, { iconName: checked ? Icons_1.UiIcons.SwitchOn : Icons_1.UiIcons.SwitchOff, style: ICON_STYLE }), thumbElement);
            }
        }
    }
    /**
     * Method returns size of margin bottom for root container depending on current props state.
     *
     * @param {string} [message] Validation message.
     * @returns {number | undefined} Value for margin bottom.
     */
    getMarginBottom(message) {
        const { inlineLabel } = this.props;
        if (message) {
            return inlineLabel ? 0 : 4;
        }
        return undefined;
    }
    /**
     * @returns {JSX.Element}
     */
    render() {
        const { inlineLabelLeft, labelFlexGrow, inlineLabel } = this.props;
        const sizeInfo = TOGGLE_SIZE;
        const messageInfo = (0, ValidationMessage_1.getMessageInfo)(this.props);
        const styles = (styleProps) => {
            return {
                root: {
                    ...(labelFlexGrow && {
                        flexGrow: 1,
                        justifyContent: 'space-between'
                    }),
                    margin: sizeInfo?.margin,
                    marginBottom: this.getMarginBottom(messageInfo.message)
                },
                label: {
                    color: 'var(--vscode-foreground)',
                    fontWeight: 'normal',
                    fontSize: sizeInfo?.label.fontSize,
                    padding: sizeInfo?.label.padding,
                    ...(inlineLabel && { marginLeft: 10 }),
                    ...(inlineLabelLeft && {
                        order: 0,
                        marginLeft: 0,
                        marginRight: 10
                    }),
                    opacity: this.props.disabled ? DISABLED_OPACITY : 'inherit'
                },
                pill: {
                    height: sizeInfo?.height,
                    width: sizeInfo?.width,
                    padding: sizeInfo?.padding,
                    background: COLORS.pill.checked.background,
                    borderColor: COLORS.pill.checked.borderColor,
                    borderStyle: 'solid',
                    ':hover .ms-Toggle-thumb': {
                        background: COLORS.thumb.checked.hover.background,
                        borderColor: COLORS.thumb.checked.hover.borderColor
                    },
                    ':hover': {
                        background: COLORS.pill.checked.hover.background,
                        borderColor: COLORS.pill.checked.hover.borderColor
                    },
                    ':disabled': {
                        background: COLORS.pill.checked.background,
                        borderColor: COLORS.pill.checked.borderColor,
                        opacity: DISABLED_OPACITY
                    },
                    ...(!styleProps.checked && {
                        background: COLORS.pill.unchecked.background,
                        borderColor: COLORS.pill.unchecked.borderColor,
                        borderStyle: 'solid',
                        // This is a bug: the best implementation approach is to set hover styles in the "thumb" section.
                        // However, the hover styles for the unchecked thumb don't work properly
                        ':hover .ms-Toggle-thumb': {
                            background: COLORS.thumb.unchecked.hover.background,
                            borderColor: COLORS.thumb.unchecked.hover.borderColor
                        },
                        ':hover': {
                            background: COLORS.pill.unchecked.hover.background,
                            borderColor: COLORS.pill.unchecked.hover.borderColor
                        },
                        ':disabled': {
                            background: COLORS.pill.unchecked.background,
                            borderColor: COLORS.pill.unchecked.borderColor,
                            opacity: DISABLED_OPACITY
                        }
                    }),
                    selectors: {
                        ':focus::after': {
                            // Overwrite flunt ui focus borders
                            border: 'none !important',
                            outline: COLORS.pill.focus.outline
                        }
                    }
                },
                thumb: {
                    height: sizeInfo?.circle.height,
                    width: sizeInfo?.circle.width,
                    borderWidth: sizeInfo?.circle.borderWidth,
                    backgroundPosition: 'center',
                    borderColor: COLORS.thumb.checked.borderColor,
                    backgroundColor: COLORS.thumb.checked.background,
                    ':hover': {
                        background: COLORS.thumb.checked.hover.background,
                        borderColor: COLORS.thumb.checked.hover.borderColor
                    },
                    ...(!styleProps.checked && {
                        borderColor: COLORS.thumb.unchecked.borderColor,
                        backgroundColor: COLORS.thumb.unchecked.background
                    }),
                    'svg': {
                        width: '100%',
                        height: '100%',
                        path: {
                            fill: styleProps.checked
                                ? 'var(--vscode-button-foreground)'
                                : 'var(--vscode-button-secondaryForeground)'
                        }
                    }
                }
            };
        };
        const toggleComponent = (react_1.default.createElement(react_2.Toggle, { ...this.props, styles: styles, ref: this.toggleRootRef, onChange: this.handleChange }));
        return messageInfo.message ? (react_1.default.createElement(ValidationMessage_1.MessageWrapper, { message: messageInfo }, toggleComponent)) : (toggleComponent);
    }
}
exports.UIToggle = UIToggle;
//# sourceMappingURL=UIToggle.js.map