import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useRef, useState } from 'react';
import { StyleSheet, Text } from 'react-native';
import MpxPickerView from '../mpx-picker-view';
import MpxPickerViewColumn from '../mpx-picker-view-column';
import { regionData } from './regionData';
import { extendObject, useUpdateEffect } from '../utils';
const styles = StyleSheet.create({
    pickerContainer: {
        height: 240,
        paddingHorizontal: 10,
        borderTopLeftRadius: 10,
        borderTopRightRadius: 10
    },
    pickerIndicator: {
        height: 45
    },
    pickerItem: {
        fontSize: 16,
        lineHeight: 45,
        textAlign: 'center'
    }
});
const rangeProvince = regionData.map(item => item.value);
const findIndex = (arr, val) => {
    const res = arr.findIndex(item => item === val);
    return res === -1 ? 0 : res;
};
const getColumnLength = (level) => {
    if (level === 'province') {
        return 1;
    }
    else if (level === 'city') {
        return 2;
    }
    else {
        return 3;
    }
};
const valueStr2Obj = (value = [], limit, customItem = '') => {
    const offsetIndex = customItem ? 1 : 0;
    let indexProvince = 0;
    if (customItem && value[0] === customItem) {
        indexProvince = 0;
    }
    else {
        indexProvince = findIndex(rangeProvince, value[0]) + offsetIndex;
    }
    const ans = {
        indexArr: [indexProvince],
        rangeArr: [customItem ? [customItem, ...rangeProvince] : rangeProvince]
    };
    for (let i = 1, lastIndex = indexProvince, lastData = regionData, lastRange = rangeProvince; i < limit; i++) {
        if (customItem) {
            if (lastIndex === 0) {
                if (i === 1) {
                    ans.indexArr.push(0, 0);
                    ans.rangeArr.push([customItem], [customItem]);
                }
                else {
                    ans.indexArr.push(0);
                    ans.rangeArr.push([customItem]);
                }
                return ans;
            }
        }
        lastData = lastData[lastIndex - offsetIndex].children;
        lastRange = lastData.map((item) => item.value);
        lastIndex = findIndex(lastRange, value[i]) + offsetIndex;
        if (customItem && customItem === value[i]) {
            lastIndex = 0;
        }
        ans.indexArr.push(Math.max(0, lastIndex));
        ans.rangeArr.push(customItem ? [customItem, ...lastRange] : lastRange);
    }
    return ans;
};
const valueChanged2Obj = (currentObj, value, limit = 3, customItem = '') => {
    const offsetIndex = customItem ? 1 : 0;
    const newValue = new Array(limit).fill(0);
    const currentValue = currentObj.indexArr;
    for (let i = 0; i < limit; i++) {
        if (i === limit - 1) {
            return {
                indexArr: value,
                rangeArr: currentObj.rangeArr
            };
        }
        newValue[i] = value[i];
        if (currentValue[i] !== value[i]) {
            break;
        }
    }
    const ans = {
        indexArr: [newValue[0]],
        rangeArr: [currentObj.rangeArr[0]]
    };
    let data = regionData;
    for (let i = 1; i < limit; i++) {
        if (customItem) {
            if (newValue[i - 1] === 0) {
                if (i === 1) {
                    ans.indexArr.push(0, 0);
                    ans.rangeArr.push([customItem], [customItem]);
                }
                else {
                    ans.indexArr.push(0);
                    ans.rangeArr.push([customItem]);
                }
                return ans;
            }
        }
        data = data[newValue[i - 1] - offsetIndex].children;
        const range = data.map(item => item.value);
        ans.indexArr.push(newValue[i]);
        ans.rangeArr.push(customItem ? [customItem, ...range] : range);
    }
    return ans;
};
const valueNum2String = (value, customItem = '') => {
    let data = regionData;
    return value.map(index => {
        if (customItem) {
            if (index === 0) {
                return customItem;
            }
            else {
                index -= 1;
            }
        }
        const item = data[index];
        data = item.children;
        return item.value;
    });
};
const hasDiff = (currentValue, value, limit = 3) => {
    for (let i = 0; i < limit; i++) {
        if (currentValue[i] !== value[i]) {
            return true;
        }
    }
    return false;
};
const PickerRegion = forwardRef((props, ref) => {
    const { value = [], level = 'region', 'custom-item': customItem = '', bindchange } = props;
    const nodeRef = useRef(null);
    const columnLength = useMemo(() => getColumnLength(level), [level]);
    const [formatObj, setFormatObj] = useState(valueStr2Obj(value, columnLength, customItem));
    const updateValue = useCallback((value = []) => {
        const calibratedValue = valueStr2Obj(value, columnLength, customItem);
        setFormatObj(calibratedValue);
    }, [columnLength, customItem]);
    const _props = useRef(props);
    _props.current = props;
    useImperativeHandle(ref, () => ({
        updateValue,
        getNodeInstance: () => ({
            props: _props,
            nodeRef,
            instance: {
                style: {}
            }
        })
    }));
    useUpdateEffect(() => {
        const calibratedValue = valueStr2Obj(value, columnLength, customItem);
        if (hasDiff(formatObj.indexArr, calibratedValue.indexArr, columnLength)) {
            setFormatObj(calibratedValue);
        }
    }, [value, columnLength, customItem]);
    const onChange = useCallback((e) => {
        const { value } = e.detail;
        const currentValue = formatObj.indexArr;
        const newObj = valueChanged2Obj(formatObj, value, columnLength, customItem);
        if (hasDiff(currentValue, value, columnLength)) {
            setFormatObj(newObj);
        }
        bindchange?.({ detail: { value: valueNum2String(newObj.indexArr, customItem) } });
    }, [formatObj, columnLength, customItem, bindchange]);
    const renderColumn = () => {
        return formatObj.rangeArr?.map((item, index) => (
        // @ts-expect-error ignore
        <MpxPickerViewColumn key={index}>
          {item.map((item, index) => {
                const len = item.length;
                const style = extendObject({}, styles.pickerItem, {
                    fontSize: len > 5 ? 21 - len : 16
                });
                return <Text key={index} style={style}>
              {item}
            </Text>;
            })}
        </MpxPickerViewColumn>));
    };
    return (<MpxPickerView style={styles.pickerContainer} indicator-style={styles.pickerIndicator} value={formatObj.indexArr} bindchange={onChange}>
      {renderColumn()}
    </MpxPickerView>);
});
PickerRegion.displayName = 'MpxPickerRegion';
export default PickerRegion;
