import React from "react";
import * as Tools from 'jad-tool';

export type OptionType = {
    key: string | number,
    title?: string,
    fullName?: (string)[],
    parent?: OptionType,
    children?: OptionType[],
    checked?: boolean,
    halfChecked?: boolean,
    checkable?: boolean,
    selectable?: boolean,
    disabled?: boolean,
    [propName: string]: any,
};
export type PropsKeyValue = {
    propPValue: string,
    propValue: string,
    propName: string,
}
// tree => flat
export function transform2FlatData(treeData: OptionType[], keyValue: PropsKeyValue, rootPid: string | number) {
    if (!treeData.length) return [];
    const { propPValue, propValue } = keyValue;
    let flatData = [];
    const tree2Flat = (data, pid) => data.map(e => {
        flatData[flatData.length] = e;
        flatData[flatData.length - 1][propPValue] = flatData[flatData.length - 1][propPValue] || pid;
        if (e['children'] && e['children'].length) {
            tree2Flat(e['children'], e[propValue]);
        }
    });
    tree2Flat(treeData, rootPid).filter(e => e);
    return flatData;
};
// flat => tree
export const transform2TreeData = (flatData: OptionType[], keyValue: PropsKeyValue, rootPid: string | number) => {
    const { propPValue, propValue } = keyValue;
    if (!flatData.length) return [];
    const flat2Tree = (parentData: OptionType[], excptParentData: OptionType[], parent?: OptionType) => {
        return parentData.map(e => {
            const hasChildrenData = excptParentData.filter(d => d[propPValue] === e[propValue]);
            e['checked'] = e['checked'] || false;
            e['halfChecked'] = e['halfChecked'] || false;
            if (e && parent)
                e['parent'] = parent;
            if (hasChildrenData && hasChildrenData.length)
                e['children'] = flat2Tree(hasChildrenData, excptParentData, e);
            return e;
        }).filter(e => e);
    }
    return flat2Tree(flatData.filter(e => e[propPValue] === rootPid), flatData.filter(e => e[propPValue] !== rootPid));
};
// 根据 checkedKeys 初始化 options、optionsFlat、checkedOptions，更新其属性 checked、halfChecked 状态。传入的 checkedKeys 是数组类型，选中项集合
// 利用引用类型的特性
export function initOptions(options: OptionType[], checkedKeys: any[]) {
    const { propValue } = this.keyValue;
    const { rootPid } = this.props;
    if (!options || !options.length) {
        console.warn(`TreeSelectSearch initOptions options has some problems`)
        return { options: [], optionsFlat: [], checkedOptions: [] };
    }
    if (!checkedKeys || !checkedKeys.length) {
        const newOptionsFlat = transform2FlatData(options, this.keyValue, rootPid);
        const newCheckedOptions = [];
        return { options: options, optionsFlat: newOptionsFlat, checkedOptions: newCheckedOptions };
    }
    function walk(walkKeys: any[], walkOptions: OptionType[]) {
        walkOptions.forEach(item => {
            if (Tools.isExist(item[propValue]) && walkKeys.includes(item[propValue])) {
                onCheckHigh2Low(true, item)
                onCheckLow2High(true, item)
            } else if (Tools.isExist(item[propValue]) && !walkKeys.includes(item[propValue])) {
                if (item.children && item.children.length) {
                    walk(walkKeys, item.children)
                }
            } else {
                console.error(`Please check: TreeSelectSearch initOptions walk item[propValue] which is ${item[propValue]}`)
            }
        })
    }
    walk(checkedKeys, options);
    const newOptionsFlat = transform2FlatData(options, this.keyValue, rootPid);
    const newCheckedOptions = getCheckedTreeOptions(options);
    const newCheckedAllStatus = options.every(item => item['checked']);
    return { options: options, optionsFlat: newOptionsFlat, checkedOptions: newCheckedOptions, checkedAllStatus: newCheckedAllStatus };

}
// 修改单个选项的状态
export function updateOption(checked: boolean, record: OptionType) {
    onCheckHigh2Low(checked, record)
    onCheckLow2High(checked, record)
}
// 从高到低
export function onCheckHigh2Low(checked: boolean, record: OptionType) {
    record['checked'] = checked;
    record['halfChecked'] = false; // 从高到低，halfChecked 其实可直接设置为 false 的值，不需要遍历 children 的 checked
    if (record['children'] && record['children'].length) {
        record['children'].forEach(child => {
            onCheckHigh2Low(checked, child)
        })
    }
}
// 从低到高
export function onCheckLow2High(checked: boolean, record: OptionType) {
    record['checked'] = checked;
    if (!record['parent']) {
        return
    } else {
        let parentChildren = record['parent']['children'] || [];
        let flag = false;
        if (parentChildren.every(item => item.checked)) {
            flag = true;
        }
        if (!flag && parentChildren.some(item => item.checked || item.halfChecked)) {
            record['parent']['halfChecked'] = true;
        } else {
            record['parent']['halfChecked'] = false;
        }
        record['parent']['checked'] = flag;
        onCheckLow2High(flag, record['parent'])
    };
}

// 获取已选中的树状结构 checkedTreeOptions
export function getCheckedTreeOptions(options: OptionType[]) {
    let checkedTreeOptions; // tree (包含halfChecked === true || checked === true)
    function loop(data: OptionType[]) {
        const newData = data.filter(item => item.checked || item.halfChecked).map(obj => {
            if (obj['children'] && obj['children'].length && (!obj.checked && obj.halfChecked)) { // 有 children 且 并没有全选时
                const children = loop(obj['children'])
                const newObj = { ...obj, children }
                return newObj
            } else return obj;
        })
        return newData
    }
    checkedTreeOptions = loop(options)
    return checkedTreeOptions
}
