import React from 'react';
import { useField, Form, FormikProps, Formik } from 'formik';
import {
    Select, Textarea, VStack, Checkbox, Button, HStack,
} from '@chakra-ui/react'
import 'suneditor/dist/css/suneditor.min.css'; // Import Sun Editor's CSS File
import Settings from "./settings";
import WorkSpace from "./workSpace";
import Header from "./header";
import { saveCondition, getCondition } from "./lsBacking";
import type {ElementsOfObject} from "./questionTypes"
//Значения, собираемые для отправки на бэк
interface Values {
    title: string;
    children: string;
    description: string;
}


const types = [
    {desc:"текст", value:"text"},
    {desc:"селект", value:"select"},
    {desc:"чекбокс", value:"checkbox"},
    {desc:"файл", value:"file"},
    {desc:"кнопка", value:"button"},
    {desc: "описание", value: "description"},
    {desc:"ничего", value:"none"},
]
export const TextField = (props: any) => {

    const [field, meta, helpers] = useField(props);

    return (
        <>
            <Textarea resize="none" width="80%" {...field} {...props} />
            {meta.touched && meta.error ? (
                <div className="error">{meta.error}</div>
            ) : null}
        </>
    );
};

const getFreeNumber = (array:Array<ElementsOfObject>):number => {
    // Для первого элемента в списке
    if (array.length === 0) {
        return(0)
    } else {
        //Для всех последующих элементов

        //Создаём массив, состоящий из id всех существующих модалок
        let indexes:any = []
        //И берём только последние числа от строк, превращая их в числа
        for (let i = 0; i < array.length; i++) {
            indexes.push(Number(array[i].id.slice(-1)))
        }
        //Сортируем в порядке возрастания
        indexes.sort(function compare(a:any, b:any):any {
                if (a < b) { return -1;}
                if (a > b) { return 1;}
                return 0;
            }
        )
        let max = indexes[indexes.length - 1]

        //Создаём массив - маску от 0 до самого высокого значения id
        let mask:any = []
        for (let i = 0; i <= max; i++) {
            mask.push(i)
        }

        //Ищем разницу между существующими id окон и маской. Список пропущенных значений есть список доступных имён.
        let difference = indexes
            .filter((num:any):any => !mask.includes(num))
            .concat(mask.filter((num:any):any => !indexes.includes(num)));

        // difference - массив нехватающих в списке номеров.
        // Если все окна у нас по порядку, без пропусков - нужно добавить новый номер
        if (difference.length === 0) {
            return(max + 1)
        } else {
            //Иначе добавить нехватающий
            return(difference[0])
        }
    }
}
const getIndexById = (id:string, array:Array<ElementsOfObject>):number => {
    let index
    for (let i = 0; i <= array.length; i++) {
        if (array[i] !== undefined) {
            if (array[i].id === id) {
                index = i
                break
            }
        }
    }
    if (typeof index === "number") {
        return index
    } else {
        console.log("Я не нашёл нужный индекс, вывел 0")
        return 0
    }

}
const getObjectFromId = (id:string, array:any):any => {
    let indexes = id.split("")
    //буфер содержит id всех родителей (от ребёнка до первого родителя)
    let bufer = []
    for (let i = 0; i < indexes.length; i++) {
        let val = (id.length - i)
        bufer.push(id.substring(0, val))
    }
    let parentObj = array
    for (let i = 0; i < indexes.length - 1; i++) {
        let id = bufer[bufer.length - i - 1]
        parentObj = parentObj[getIndexById(id, parentObj)].children
    }
    if (parentObj.length > 1) {
        parentObj = parentObj[Number(id.slice(-1))]
    }
    if (Array.isArray(parentObj)) {
        return parentObj[0]
    } else {
        return parentObj
    }

}

export default () => {

    // const [stockroom, setStockroom] = React.useState<Array<ElementsOfObject>>([
    const [stockroom, setStockroom] = React.useState<any>([
        {id: "0", type: 7, children: [
            {
                id: "00", type: 7, children: [
                    {id: "000", children: [], type: 4}
                ]
            },
            {
                id: "01", type: 7, children: [
                    {
                        id: "010", children: [
                            {id: "0100", children: [], type: 4},
                            {id: "0101", children: [], type: 4}
                        ], type: 7
                    }
                ]
            },
            {id: "02", type: 4, children: []}
        ]}
    ])
    const [focus, setFocus] = React.useState<string | undefined>("101") //Хранит путь объекта

    const setNewFocus = (value:string, multiFocus:boolean) => {
        //Фокусы ставятся или удаляются от клика по уже созданным элементам.
        if (multiFocus) {
            //Клик ЛКМ + shift - мультивыбор

        } else {
            //Клик ЛКМ - единичный выбор.
            setFocus(value)
        }
    }
    // Изменение типа очищает все поля
    const createNewTree = (value:any, tree = stockroom) => {
        return (
        tree.map((node: any) => {

            if (node.id === focus) {
                let obj = {
                    ...node,
                    ...value,
                }
                return (obj)
            } else if (node.children.length !== 0) {
                return {
                    ...node,
                    children: createNewTree(value, node.children)
                }
            } else {
                return node
            }
        })
    )}
    const typeHC = (type:any): void => {
        if (focus !== undefined) {
            setStockroom(createNewTree({type:type}))
        }
    }
    const colorHC = (color:any) => {
        if (focus !== undefined) {
            setStockroom(createNewTree({color:color}))
        }
    }


    const createObject = (obj:any, type:number = 4) => {
        if (focus !== undefined) {
            //Созданный объект добавляется после объекта с фокусом
            //Если фокусный элемент - контейнер, добавление происходит внутрь него
            //
            const focusedObj = getObjectFromId(focus, stockroom)
            const creacteChildrens = (arr = stockroom) => {
                return arr.map((node: any) => {
                    if (node.children.length !== 0) {
                        //Объект с детьми должен быть добавлен + должен произойти вызов для поля children
                        return (
                            { ...node, children: creacteChildrens(node.children) }
                        )
                    } else {
                        //Объект без детей просто добавляется
                        return node
                    }
                })
            }

            //Находим родителя
            const parentObj = getObjectFromId(focus.slice(0,-1), stockroom)
            //Находим свободный ид
            let newId:any = getFreeNumber(parentObj.children)
            newId = focus.slice(0,-1) + newId
            //Создаём новый объект
            const newObj = {
                id: newId,
                type: type,
                children: []
            }

            if (focusedObj.type === 7) {
                //Кладём внутрь фокусного объекта

                console.log(focusedObj)

                focusedObj.children = [...focusedObj.children, newObj]

                console.log(focusedObj)
                setStockroom(createNewTree(focusedObj))

            } else {
                //Кладём рядом с фокусным объектом

                //Создаём новый массив для поля children родителя и присваиваем его
                let newCildrenArr = []
                for (let i = 0; parentObj.children.length > i ; i++) {
                    let node = parentObj.children[i]
                    if (node.id === focus) {
                        newCildrenArr.push(node)
                        newCildrenArr.push(newObj)
                    } else {
                        newCildrenArr.push(node)
                    }
                }
                parentObj.children = newCildrenArr

                //Создаём дерево с обновлённым родителем
                const newTree = creacteChildrens()
                setStockroom(newTree)
            }
        }
    }
    // const changeFocus = (id: number): void => {
    //     //Не менять фокус если снова выбрано то же окно
    //     if (focus !== id) {
    //         //Хранилище с отменённым фокусом у объектов (по задумке у одного элемента)
    //         let newArr = stockroom.map((e:ElementsOfObject) => {
    //             e.isFocus = false
    //             return e
    //         })
    //
    //         //Получаем индексы фокусированных объектов. Новый и, если есть, старый
    //         let index = getIndexById(id, stockroom)
    //
    //         //Устанавливаем новый фокус и пересоздаём массив
    //         setFocus(id)
    //         saveCondition("focus", id)
    //
    //         newArr[index].isFocus = true
    //         setStockroom([...newArr])
    //     }
    // }
    // const changeBgColor = (color: string): void => {
    //     if (focus !== undefined) {
    //         let index = getIndexById(focus, stockroom)
    //
    //         let newArr = stockroom
    //         newArr[index].color = color
    //         setStockroom([...newArr])
    //         saveCondition("stockroom", newArr)
    //     }
    // }
    // const changeText = (text: string): void => {
    //     if (focus !== undefined) {
    //         let index = getIndexById(focus, stockroom)
    //         let newArr = stockroom
    //         newArr[index].text = text
    //         setStockroom([...newArr])
    //         saveCondition("stockroom", newArr)
    //     }
    // }
    //
    // const createObject = (obj:ElementsOfObject) => {
    //
    //     //Получаем и присваиваем первый свободный айдишник (по возрастанию)
    //     const free = getFreeNumber(stockroom)
    //     obj.id = free
    //
    //     //Хранилище с отменённым фокусом у объектов (по задумке у одного элемента)
    //     let newArr = stockroom.map((e:ElementsOfObject) => {
    //         e.isFocus = false
    //         return e
    //     })
    //
    //     //Мы должны вставить новый объект следующим после того, на котором фокус. Это достигается позиционированием в массив
    //     if (focus === undefined){ //фокуса нет - добавляем в конец массива
    //         newArr.push(obj)
    //         setStockroom([...newArr])
    //         saveCondition("stockroom", newArr)
    //         //Говорим стейту с фокусом, что фокус изменился
    //         setFocus(newArr.length - 1)
    //     } else { //фокус есть - добавляем после объекта с фокусом
    //
    //
    //
    //         let index = getIndexById(focus, stockroom)
    //         let current = stockroom[index]
    //         //Объект в фокусе - контейнер. Новый объект создаётся с указанием, что контейнер - родитель
    //         if (current.type === 7) {
    //             obj.parent = current.id
    //         }
    //
    //         newArr.splice(index + 1, 0, obj)
    //
    //         //Говорим стейту с фокусом, что фокус изменился
    //         setFocus(index + 1)
    //         setStockroom([...newArr])
    //         saveCondition("stockroom", newArr)
    //     }
    // }
    // const deleteObject = (id: number): void => {
    //     let index = getIndexById(id, stockroom)
    //     //Проверка, что объект с таким id существует
    //     if (stockroom[index] !== undefined) {
    //         //Если удалён был фокусный объект - фокус теперь неизвестен
    //         if (stockroom[index].isFocus) {
    //             setFocus(undefined)
    //         }
    //
    //         let newArr:any = []
    //         //Если удалённый объект был хранилищем (контейнером, или селектом), мы не вложим в новый массив его и его потомков
    //         if (stockroom[index].type === 1 || stockroom[index].type === 7) {
    //             stockroom.forEach((e:any, i:number) => {
    //                 if (e.id !== id) {
    //                     if (e.parent !== id) {
    //                         newArr.push(e)
    //                     } else {
    //                         if (e.isFocus) {
    //                             setFocus(undefined)
    //                         }
    //                     }
    //                 }
    //             })
    //         } else {
    //             newArr = stockroom
    //             newArr.splice(index, 1)
    //         }
    //         setStockroom([...newArr])
    //         saveCondition("stockroom", newArr)
    //     }
    // }
    return(
        <>
            <Header/>
            <HStack
                justifyContent="space-between"
                alignItems="normal"
            >
                <VStack
                    minWidth="200px"
                    bgColor="lightgray"
                    height="98vh"
                    padding="10px"
                    >

                </VStack>

                <VStack>
                    <WorkSpace
                        stockroom={stockroom}
                        setNewFocus={setNewFocus}
                        focus={focus}
                    />
                </VStack>

                <VStack
                    minWidth="250px"
                    bgColor="lightgray"
                    height="98vh"
                    padding="10px"
                    overflow="auto"
                    >
                    <Settings
                        types={types}
                        stockroom={stockroom}
                        typeHC={typeHC}
                        focus={focus}
                        changeFocus={stockroom}
                        changeBgColor={colorHC}
                        changeText={stockroom}
                        getIndexById={getIndexById}
                        createObject={createObject}
                        deleteObject={stockroom}
                    />
                    <Button onClick={() => {
                        console.log(stockroom)
                    }}>info</Button>
                </VStack>
            </HStack>
        </>
    )
}
