/* Рекурсия: HTML tree
Используя решение этого задания сделайте функцию, которая рекурсивно создает HTML-строку из древовидной структуры данных Javascript любой вложенности. Проверьте результат работы функции выводя HTML-строку используя document.write или же какой-то_элемент.innerHTML*/

{
    const table = {
        tagName: 'table',
        attrs: {
            border: "1",
        },
        children: [
            {
                tagName: 'tr',
                children: [
                    {
                        tagName: "td",
                        children: ["1x1"],
                    },
                    {
                        tagName: "td",
                        children: ["1x2"],
                    },
                ]
            },
            {
                tagName: 'tr',
                children: [
                    {
                        tagName: "td",
                        children: ["2x1"],
                    },
                    {
                        tagName: "td",
                        children: ["2x2"],
                    },
                ]
            }
        ]
    }
    //htmlTree(table) //вернет <table border='1' ....

    function recursion (obj) {
        
        let result=""
        
        console.log(obj.tagName)
        result += "<" + obj.tagName
        if (obj.attrs){
            for (property in obj.attrs) {
                result += ' ' + property + '="' + obj.attrs[property] + '"'
            }
        }
        result += ">"

        console.log(obj.children)
        
        let children
        if (obj.children){

            children = obj.children
            for (const obj of children){
                console.log(obj)
            if (typeof obj !== 'object') {
                result += obj
            }
            if(typeof obj === 'object') {
                 result += recursion (obj)
            }
            }

        }

        result += "</" + obj.tagName + ">"
        return result
    }

    recursion(table)


    const body = {
        tagName : 'body',
        children : [
            {
                tagName : 'div',
                children : [
                    {
                        tagName : 'span',
                        children : ['Enter a data please:']
                    },
                    {
                        tagName : 'br'
                    },
                    {
                        tagName : 'input',
                        attrs : {
                            type : 'text',
                            id : 'name'
                        }
                    },
                    {
                        tagName : 'input',
                        attrs : {
                            type : 'text',
                            id : 'surname',
                        }
                    }
                ]
            },
            {
                tagName : 'div',
                children : [
                    {
                        tagName : 'button',
                        attrs : {
                            id : 'ok'
                        },
                        children : ['OK']
                    },
                    {
                        tagName : 'button',
                        attrs : {
                            id : 'cancel'
                        },
                        children : ['Cancel']
                    },
                ]
            }
        ]
    }

    recursion(body)

}

/* Рекурсия: DOM tree
Используя решение этого задания сделайте функцию, которая рекурсивно создает DOM из древовидной структуры данных Javascript. Задание в целом аналогично предыдущему, однако вместо накопления результата в HTML-строке функция должна добавлять элементы созданные через document.createElement в переданного в функцию родителя.
const table = {
    ........
}
domTree(document.body, table)*/

{
    function recursion (parent, obj) {
        const elem = document.createElement(obj.tagName)
        parent.append(elem)

        if (obj.attrs){
            for (property in obj.attrs) {
                elem[property] = obj.attrs[property]
            }
        }

        let children
        if (obj.children){


            children = obj.children
            for (const obj of children){
                
            if (typeof obj !== 'object') {
                //result += obj
                elem.innerText = obj
            }
            if(typeof obj === 'object') {
                recursion (elem, obj)
            }
            }

        }

    }

    const section = {
        tagName : 'section',
        children : [
            {
                tagName : 'div',
                children : [
                    {
                        tagName : 'span',
                        children : ['Enter a data please:']
                    },
                    {
                        tagName : 'br'
                    },
                    {
                        tagName : 'input',
                        attrs : {
                            type : 'text',
                            id : 'name'
                        }
                    },
                    {
                        tagName : 'input',
                        attrs : {
                            type : 'text',
                            id : 'surname',
                        }
                    }
                ]
            },
            {
                tagName : 'div',
                children : [
                    {
                        tagName : 'button',
                        attrs : {
                            id : 'ok'
                        },
                        children : ['OK']
                    },
                    {
                        tagName : 'button',
                        attrs : {
                            id : 'cancel'
                        },
                        children : ['Cancel']
                    },
                ]
            }
        ]
    }

    recursion(document.body, section)
}

/*Рекурсия: Deep Copy
Напишите функцию, которая рекурсивно осуществляет глубокое копирование структур Javascript, в которых нет циклических связей.
const arr  = [1,"string", null, undefined, {a: 15, b: 10, c: [1,2,3,4],d: undefined, e: true }, true, false]
const arr2 = deepCopy(arr) //arr2 и все его вложенные массивы и объекты - другие объекты, которые можно менять без риска поменять что-то в arr
const table2 = deepCopy(table) //аналогично*/

{
    const arr = [1, "string", null, undefined, { a: 15, b: 10, c: [1, 2, 3, 4], d: undefined, e: true }, true, false]
    const arr2 = deepCopy(arr)
    function deepCopy(element) {
        let result
        if (typeof element !== "object" || element === null) return result = element
        if (Array.isArray(element)) {
            result = []
            for (arrElem of element) {
                result.push(deepCopy(arrElem))
            }
            return result
        }
        if (typeof element === 'object') {
            result = {}
            for (key in element) {
                result[key] = deepCopy(element[key])
            }
            return result
        }
    }
}

/*Рекурсия: My Stringify
Напишите аналог JSON.stringify*/
/*
const jsonString = stringify(arr или table из предыдущих заданий) //напишите функцию stringify без использования JSON.stringify
console.log(JSON.parse(jsonString)) //не должно поломаться и должно вернуть структуру, во всем схожую с оригинальным arr или table
*/

{
    const table = {
        tagName: 'table',
        attrs: {
            border: "1",
        },
        children: [
            {
                tagName: 'tr',
                children: [
                    {
                        tagName: "td",
                        children: ["1x1"],
                    },
                    {
                        tagName: "td",
                        children: ["1x2"],
                    },
                ]
            },
            {
                tagName: 'tr',
                children: [
                    {
                        tagName: "td",
                        children: ["2x1"],
                    },
                    {
                        tagName: "td",
                        children: ["2x2"],
                    },
                ]
            }
        ]
    }




    function stringify(obj) {
        let result = ``

        if (typeof obj === 'number' ||
            typeof obj === 'boolean' ||
            obj === null) return result += obj

        if (typeof obj === 'string') return result += `"${obj}"`

        if (Array.isArray(obj)) {
            result += `[`

            if (obj.length > 0) {
                for (arrItem of obj) {
                    result += `${stringify(arrItem)},`
                }
                result = result.slice(0, result.length - 1)
            }

            result += `]`
            return result
        }

        if (typeof obj === 'object') {
            result += `{`
            if (Object.keys(obj).length > 0) {
                for (key in obj) {
                    result += `"${key}":`

                    result += `${stringify(obj[key])},`
                }
                result = result.slice(0, result.length - 1)
            }
            result += `}`
        }
        return result
    }

    let a = stringify(table)
    console.log(a)
    let b = JSON.parse(a)
    console.log(b)
}

/*Рекурсия: getElementById throw
Напишите функцию getElementById, которая будет аналогична document.getElementById. В качестве основы можете взять материал лекции (walker), однако в цикл перебора children вставьте проверку на нахождение переданного id. При нахождении элемента по id в рекурсивной функции выбрасывайте исключение со значением найденного DOM-элемента, которое будет поймано на уровне вашей функции getElementById, после чего она вернет выброшенный DOM-элемент. */

{
    function getElementById(idToFind) {
        function walker(parent = document.body) {

            for (const child of parent.children) {
                if (child.id === idToFind) throw child
                walker(child)
            }
        }


        try {
            walker(parent = document.body)
            return undefined
        } catch (element) { return element }
    }

    //ищем id = 'h1-1' на http://doc.a-level.com.ua/five-recursion-try-catch-finally
    let element = getElementById('h4-7_19')
    console.log(element)
}