// fetch basic
// Исследуйте сайт swapi.dev, рассмотрите JSON - ы, которые предоставляются этим сервисом(например: https://swapi.dev/api/people/1/, https://swapi.dev/api/people/2/, https://swapi.dev/api/starships/12/
//С помощью следующего кода считать и вывести информацию о Люке Скайвокере:
// Напишите функцию для отображения любого JSON в форме таблицы.Функция должна принимать два параметра:
// DOM - элемент, в котором строится таблица
// JSON, который нужно отобразить.
{
    fetch('https://swapi.dev/api/people/1/')
        .then(res => res.json())
        .then(luke => {
            starWarsData(document.body, luke)
        })

    function starWarsData(parent, data) {
        const table = document.createElement('table')
        table.style.cssText = `
            border: 1px solid black;
            border-collapse: collapse;`
        parent.append(table)

        for (let [key, value] of Object.entries(data)) {
            const row = document.createElement('tr')
            table.append(row)

            let col = document.createElement('td')
            col.innerText = `${key}`
            col.style.cssText = `
            border: 1px solid black;
            padding: 5px 10px;`
            row.append(col)

            col = document.createElement('td')
            col.innerText = `${value}`
            col.style.cssText = `
            border: 1px solid black;
            padding: 5px 10px;`
            row.append(col)
        }
    }
}



// fetch improved
// Расширить функцию отображения:
//  Если одно из полей строка или массив.
//  Если строки или строка содержат в себе https://swapi.dev/api/
//  То выводить вместо текста строки кнопку, при нажатии на которую:
//      делается fetch данных по этой ссылке
//      функция отображения запускает сама себя(рекурсивно) для отображения новых данных в том же элементе.
{
    function starWarsData(parent, data) {
        // create Table
        const table = document.createElement('table')
        table.style.cssText = `
            border: 1px solid black;
            border-collapse: collapse;
            margin: 10px;`
        parent.append(table)

        // create table Header
        const tableHead = document.createElement('tr')
        table.append(tableHead)

        const colHead = document.createElement('td')
        colHead.innerText = Object.values(data)[0]
        colHead.colSpan = 2
        colHead.style.cssText = `
        background-color: #a0a0a0;
        text-align: center;
        font-size: 1.5em;
        font-weight: 900;
        line-height: 1.5em;`
        tableHead.append(colHead)

        // create table Body
        for (const [key, values] of Object.entries(data)) {

            // create row
            const row = document.createElement('tr')
            table.append(row)

            // create first cell with key
            let col = document.createElement('td')
            col.innerText = key
            col.style.cssText = `
            border: 1px solid black;
            padding: 5px 10px;`
            row.append(col)

            // create second cell
            col = document.createElement('td')
            col.style.cssText = `
            border: 1px solid black;
            padding: 5px 10px;`

            // cheking string or array(object)
            if (typeof values !== 'object') {
                if (!(values.toString().includes('swapi.dev/api'))) {
                    col.innerText = values
                    col.style.cssText = `
                    border: 1px solid black;
                    padding: 5px 10px;`
                    row.append(col)
                } else {
                    row.append(col)
                    createBtn(col, values)
                }
            } else {
                row.append(col)
                for (const value of values) {
                    createBtn(col, value)
                }
            }
        }

        // create button
        function createBtn(parent, param) {
            const btn = document.createElement('button')
            btn.innerText = param
            btn.style.margin = '5px'
            parent.append(btn)

            btn.onclick = () => {
                fetch(param)
                    .then(res => res.json())
                    .then(item => {
                        starWarsData(parent, item)
                    })
                btn.disabled = true
            }
        }
    }

    // start parsing
    fetch('https://swapi.dev/api/people/1/')
        .then(res => res.json())
        .then(luke => {
            starWarsData(document.body, luke)
        })
}



// race
// Используя Promise.race запустите запрос на API(swapi.dev) параллельно с delay.По результату определите, что было быстрее, запрос по сети, или определенный интервал времени.Подберите параметр delay так, что бы результат был неизвестен изначально, и при многократных запусках быстрее был то delay, то myfetch.
{
    const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
    const promiseDelay = delay(Math.random() * 250)
        .then(result => result)

    const promiseApi = fetch('https://swapi.dev/api/people/1/')
        .then(res => res.json())
        .then(result => result)

    Promise.race([promiseDelay, promiseApi]).then((value) => console.log(value))
}



// Promisify: confirm
// Промисифицируйте confirm.Напишите функцию, которая возвращает промис, который переходит в состояние fulfilled при нажатии "OK" и реджектится при нажатии "Cancel".Функция должна принимать строку для confirm:
// Промисификация не делает confirm неблокирующей функцией.Данное задание имеет только образовательный смысл.
{
    function confirmPromise(text) {
        function executor(resolve, reject) {
            confirm(text) ? resolve() : reject()
        }
        return new Promise(executor)
    }

    confirmPromise('Промисы это сложно?').then(() => console.log('не так уже и сложно'), () => console.log('respect за усидчивость и внимательность'))
}



// Promisify: prompt
// Аналогично предыдующему заданию промисифицируйте prompt.В случае нажатия "ОК" промис резолвится и его результатом становится текст, введенный пользователем в окне prompt.В случае нажатия "Отмены" - промис реджектится.Параметром функции будет текст сообщения в prompt
{
    function promptPromise(text) {
        function executor(resolve, reject) {
            let question = prompt(text)
            question !== null && question !== '' ? resolve(question) : reject()
        }
        return new Promise(executor)
    }
    promptPromise("Как тебя зовут?").then(name => console.log(`Тебя зовут ${name}`),
        () => console.log('Ну зачем морозиться, нормально же общались'))
}



// Promisify: LoginForm
// Промисифицируйте конструктор LoginForm.В промисифицированную функцию передается DOM - элемент - родитель для формы, В колбэке, предназначенном для получения логина и пароля в момент нажатия кнопки "Login...", который вы назначаете в объекте LoginForm, зарезолвите промис.Результатом промиса должен быть объект с ключами login и password, ключи должны содержать значения полей ввода.
{
    function LoginForm(parent) {
        function Password(parent, open) {
            // create password fild
            const inputPassword = document.createElement('input')
            inputPassword.type = 'password'
            inputPassword.placeholder = 'Insert password'
            parent.append(inputPassword)

            // create checkbox
            const inputCheckbox = document.createElement('input')
            inputCheckbox.type = 'checkbox'
            inputCheckbox.checked = false
            parent.append(inputCheckbox)

            // create getters
            this.getValue = () => inputPassword.value
            this.getOpen = () => inputCheckbox.checked

            // create setters
            this.setValue = (value) => inputPassword.value = value
            this.setOpen = (open) => {
                if (open === true) {
                    inputPassword.type = 'text'
                    inputCheckbox.checked = true
                }
                if (open === false) {
                    inputPassword.type = 'password'
                    inputCheckbox.checked = false
                }
                return inputPassword.type, inputCheckbox.checked
            }

            // starting onChange
            inputPassword.addEventListener('input', () => {
                this.onChange(inputPassword.value)
            })

            // starting onOpenChange + change inputPasswor hide/see
            inputCheckbox.addEventListener('change', () => {
                this.setOpen(inputCheckbox.checked),
                    this.onOpenChange(inputCheckbox.checked)
            })
        }

        function Login(parent) {
            // create login fild
            const inputLogin = document.createElement('input')
            inputLogin.type = 'text'
            inputLogin.placeholder = 'Insert login'
            parent.append(inputLogin)

            // create getters
            this.getValue = () => inputLogin.value

            // create setters
            this.setValue = (value) => inputLogin.value = value

            // starting onChange
            inputLogin.addEventListener('input', () => {
                this.onChange(inputLogin.value)
            })
        }

        // create form with password and login
        const form = document.createElement('form')
        parent.append(form)

        const loginLabel = document.createElement('label')
        loginLabel.innerText = 'Login:'
        form.append(loginLabel)

        let breakSymbol = document.createElement('br')
        form.append(breakSymbol)

        const login = new Login(form)

        breakSymbol = document.createElement('br')
        form.append(breakSymbol)

        const passwordLabel = document.createElement('label')
        passwordLabel.innerText = 'Password:'
        form.append(passwordLabel)

        breakSymbol = document.createElement('br')
        form.append(breakSymbol)

        const password = new Password(form, true)

        breakSymbol = document.createElement('br')
        form.append(breakSymbol)

        const confirmBtn = document.createElement('button')
        confirmBtn.innerText = 'Confirm'
        confirmBtn.type = 'button'
        confirmBtn.style.marginTop = '10px'
        confirmBtn.disabled = true
        form.append(confirmBtn)

        // change confirmBtn.disabled
        function checkButton() {
            if (login.getValue() !== '' && password.getValue() !== '') {
                confirmBtn.disabled = false
            } else {
                confirmBtn.disabled = true
            }
            return confirmBtn.disabled
        }
        checkButton()

        // listening password and login
        login.onChange = password.onChange = checkButton

        // create getters
        this.getPasswordValue = () => password.getValue()
        this.getPasswordOpen = () => password.getOpen()
        this.getLoginValue = () => login.getValue()
        this.getButtonStatus = () => confirmBtn.disabled

        // create setters
        this.setPasswordValue = (value) => password.setValue(value)
        this.setLoginValue = (value) => login.setValue(value)
        this.setPasswordOpen = (status) => password.setOpen(status)

        // create callbacks
        this.onOpenChange = open => password.onOpenChange = open

        // on lobig Button
        confirmBtn.addEventListener('click', () => {
            this.confirmBtnListener()
        })

    }


    function loginPromise(parent) {
        function executor(resolve, reject) {
            const form = new LoginForm(parent)

            form.confirmBtnListener = () => resolve({
                'login': form.getLoginValue(),
                'password': form.getPasswordValue()
            })
        }

        return new Promise(executor)
    }


    loginPromise(document.body).then(({ login, password }) => console.log(`Вы ввели ${login} и ${password}`))
}