import { __assign, __awaiter, __generator } from "tslib";
import { useComponent, useEvent, useRef, useState, } from 'functional-mini/component';
import '../_util/assert-component2';
import { mountComponent } from '../_util/component';
import { useComponentEvent } from '../_util/hooks/useComponentEvent';
import { useMixState } from '../_util/hooks/useMixState';
import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect';
import { RateFunctionalProps } from './props';
var Rate = function (props) {
    var _a = useMixState(props.defaultValue, {
        value: props.value,
        postState: function (value) {
            if (props.allowHalf) {
                return {
                    valid: true,
                    value: value % 0.5 !== 0 ? Math.round(value) : value,
                };
            }
            return {
                valid: true,
                value: Math.ceil(value),
            };
        },
    }), rateValue = _a[0], _b = _a[1], isControlled = _b.isControlled, update = _b.update;
    var triggerEvent = useComponentEvent(props).triggerEvent;
    var _c = useState(null), displayValue = _c[0], setDisplayValue = _c[1];
    var ref = useRef(null);
    var instance = useComponent();
    function getInstance() {
        if (instance.$id) {
            return my;
        }
        return instance;
    }
    function getRate(clientX) {
        return __awaiter(this, void 0, void 0, function () {
            var gutter, count, _a, left, width, halfRateWidth, num, halfRateCount, val, rate;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        gutter = props.gutter, count = props.count;
                        return [4 /*yield*/, getInstanceBoundingClientRect(getInstance(), "#ant-rate-container".concat(instance.$id ? "-".concat(instance.$id) : ''))];
                    case 1:
                        _a = _b.sent(), left = _a.left, width = _a.width;
                        halfRateWidth = (width - (count - 1) * gutter) / count / 2;
                        num = clientX - left;
                        halfRateCount = 0;
                        /* eslint-disable no-constant-condition */
                        while (true) {
                            val = halfRateWidth * halfRateCount + gutter * Math.floor(halfRateCount / 2);
                            if (halfRateCount >= count * 2 || num <= val) {
                                break;
                            }
                            halfRateCount++;
                        }
                        rate = props.allowHalf
                            ? halfRateCount * 0.5
                            : Math.ceil(halfRateCount * 0.5);
                        return [2 /*return*/, rate];
                }
            });
        });
    }
    useEvent('handleStarTap', function (e) { return __awaiter(void 0, void 0, void 0, function () {
        var _a, clientX, x, clickX, rate;
        return __generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    if (props.readonly) {
                        return [2 /*return*/];
                    }
                    _a = e.detail, clientX = _a.clientX, x = _a.x;
                    clickX = typeof x === 'number' ? x : clientX;
                    return [4 /*yield*/, getRate(clickX)];
                case 1:
                    rate = _b.sent();
                    if (rateValue === rate && props.allowClear) {
                        rate = 0;
                    }
                    if (!isControlled) {
                        update(rate);
                    }
                    if (rateValue !== rate) {
                        triggerEvent('change', rate);
                    }
                    return [2 /*return*/];
            }
        });
    }); });
    useEvent('handleStarMove', function (e) { return __awaiter(void 0, void 0, void 0, function () {
        var touches, clientX, rate;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    if (props.readonly) {
                        return [2 /*return*/];
                    }
                    touches = e.touches;
                    clientX = touches[0].clientX;
                    if (!ref.current) {
                        ref.current = {
                            originalRate: rateValue,
                        };
                    }
                    return [4 /*yield*/, getRate(clientX)];
                case 1:
                    rate = _a.sent();
                    if (ref.current) {
                        ref.current = __assign(__assign({}, ref.current), { currentRate: rate });
                        if (isControlled) {
                            setDisplayValue(rate);
                        }
                        else {
                            update(rate);
                        }
                    }
                    return [2 /*return*/];
            }
        });
    }); });
    useEvent('handleStarMoveEnd', function () { return __awaiter(void 0, void 0, void 0, function () {
        var _a, currentRate, originalRate;
        return __generator(this, function (_b) {
            if (props.readonly) {
                return [2 /*return*/];
            }
            if (!ref.current) {
                return [2 /*return*/];
            }
            _a = ref.current, currentRate = _a.currentRate, originalRate = _a.originalRate;
            ref.current = null;
            if (isControlled) {
                setDisplayValue(null);
            }
            if (currentRate !== originalRate) {
                triggerEvent('change', currentRate);
            }
            return [2 /*return*/];
        });
    }); });
    return {
        mixin: {
            value: displayValue !== null ? displayValue : rateValue,
        },
    };
};
mountComponent(Rate, RateFunctionalProps);