// Переделайте задание createPerson на функцию конструктор Person.
// Для этого методы и свойства заносите не в создаваемый объект, а в this внутри конструктора.
{
    function Person(name, surName) {
        this.name = `${name}`
        this.surName = `${surName}`
        this.getFullName = function getFullName() {
            return `${this.name} ${this.fatherName || ''} ${this.surName}`
        }
    }

    const a = new Person("Вася", "Пупкин")
    const b = new Person("Анна", "Иванова")
    const c = new Person("Елизавета", "Петрова")


    console.log(a.getFullName()) //Вася Пупкин

    a.fatherName = 'Иванович'    //Вася Иванович Пупкин
    console.log(a.getFullName())

    console.log(b.getFullName())

    console.log(c.name)//Анна Иванова
}



// Person Prototype
// Переделайте предыдущее задание, вынеся методы в прототип.Для этого вместо присвоения в this занесите их в объект Person.prototype.После этой переделки все должно работать по старому:
{
    function Person(name, surName) {
        this.name = name,
            this.surName = surName
    }

    Person.prototype.name = function () {
        return this.name
    }

    Person.prototype.surName = function () {
        return this.surName
    }

    Person.prototype.getFullName = function () {
        return `${this.name} ${this.fatherName || ''} ${this.surName}`
    }

    const a = new Person("Вася", "Пупкин")
    const b = new Person("Анна", "Иванова")
    const c = new Person("Елизавета", "Петрова")


    console.log(a.getFullName()) //Вася Пупкин

    a.fatherName = 'Иванович'    //Вася Иванович Пупкин
    console.log(a.getFullName())

    console.log(b.getFullName())

    console.log(c.name)//Анна Иванова
}



// Store
// Переделайте функцию createStore(та, которая хранилище Redux) на конструктор Store.Прототип не используйте; оставьте переменные state, cbs и reducer замкнутыми.Соответственно методы subscribe, dispatch и getState должны быть объявлены внутри функции - конструктора и не могут быть в прототипе.Проверьте переделанный конструктор на вашем ДЗ по ларьку;
{
    function Store(reducer) {
        let state = reducer(undefined, {})
        let cbs = []

        let getState, dispatch, subscribe

        this.getState = () => state
        this.subscribe = cb => (cbs.push(cb),
            () => cbs = cbs.filter(c => c !== cb))

        this.dispatch = action => {
            const newState = reducer(state, action)
            if (newState !== state) {
                state = newState
                for (let cb of cbs) cb()
            }
        }
    }

    // ниже код ларька для проверки
    {
        // create Reduser
        function reducer(state, { type, ШО, СКОКА, БАБЛО, ШО_ДОБАВИТЬ, СКОКА_ДОБАВИТЬ, ЦЕНА_ДОБАВИТЬ }) {
            if (!state) {
                return {
                    касса: 200,
                    чай: 0,
                    пиво: {
                        amount: 110,
                        price: 20
                    },
                    чипсы: {
                        amount: 120,
                        price: 30
                    },
                    сиги: {
                        amount: 130,
                        price: 50
                    }
                }
            }

            if (type === 'КУПИТЬ' && СКОКА <= state[ШО].amount && БАБЛО === (СКОКА * state[ШО].price)) {
                return {
                    ...state,
                    [ШО]: {
                        amount: state[ШО].amount - СКОКА,
                        price: state[ШО].price
                    },
                    касса: state.касса + БАБЛО
                }
            }

            if (type === 'КУПИТЬ' && СКОКА <= state[ШО].amount && БАБЛО > (СКОКА * state[ШО].price)) {
                return {
                    ...state,
                    [ШО]: {
                        amount: state[ШО].amount - СКОКА,
                        price: state[ШО].price
                    },
                    касса: state.касса + (СКОКА * state[ШО].price),
                    чай: state.чай + (БАБЛО - (СКОКА * state[ШО].price))
                }
            }

            if (type === 'ДОБАВИТЬ' && !(ШО_ДОБАВИТЬ in state) && state.касса >= (СКОКА_ДОБАВИТЬ * ЦЕНА_ДОБАВИТЬ)) {
                return {
                    ...state,
                    [ШО_ДОБАВИТЬ]: {
                        amount: СКОКА_ДОБАВИТЬ,
                        price: ЦЕНА_ДОБАВИТЬ
                    },
                    касса: state.касса - (СКОКА_ДОБАВИТЬ * ЦЕНА_ДОБАВИТЬ)
                }
            }

            if (type === 'ДОБАВИТЬ' && ШО_ДОБАВИТЬ in state && state.касса >= (СКОКА_ДОБАВИТЬ * ЦЕНА_ДОБАВИТЬ)) {
                return {
                    ...state,
                    [ШО_ДОБАВИТЬ]: {
                        amount: state[ШО_ДОБАВИТЬ].amount + СКОКА_ДОБАВИТЬ,
                        price: ЦЕНА_ДОБАВИТЬ
                    },
                    касса: state.касса - (СКОКА_ДОБАВИТЬ * ЦЕНА_ДОБАВИТЬ)
                }
            }

            return state
        }
        const store = new Store(reducer)

        // create divStore
        const divStore = document.createElement('div')
        divStore.style.cssText = `
        min-width: 700px;
        width: 50%;
        border: 1px solid #A9A9A9;
        border-radius: 8px;
        box-shadow: rgb(0 0 0 / 50%) 5px 5px 5px 0px;
        padding: 20px;`
        document.body.append(divStore)

        // create divStore title
        const divStoreitle = document.createElement('h1')
        divStoreitle.innerText = 'ЛАРЕК'
        divStoreitle.style.cssText = `
    text-align: center;`
        divStore.append(divStoreitle)

        // create Table of Store
        let table, col, row

        const createTable = () => {
            table = document.createElement('table')
            divStore.append(table)

            // create names of parametrs
            const params = []
            for (const child of Object.values(store.getState())) {
                for (const key of Object.keys(child)) {
                    if (!params.includes(key)) {
                        params.push(key);
                    }
                }
            }

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

            // create first cell in Header
            col = document.createElement('td')
            row.append(col)

            // create header names
            for (const key of params) {
                col = document.createElement('td')
                col.innerText = `${key}`
                col.style.cssText = `
                font-size: 1.5em;
                padding: 5px 10px;
                margin: 0 10px;
                text-align: center;
                background-color: #D9D9D9;`
                row.append(col)
            }

            // create table body

            for (const [key, values] of Object.entries(store.getState())) {

                if (key === 'касса') {
                    row = document.createElement('tr')
                    table.append(row)

                    col = document.createElement('td')
                    col.innerText = `${key.toUpperCase()}`
                    col.style.cssText = `
                min-width: 150px;
                font-size: 2em;
                padding: 5px 10px;
                text-align: left`
                    row.append(col)

                    col = document.createElement('td')
                    col.innerText = `${values}`
                    col.style.cssText = `
                font-size: 2em;
                text-align: center;`
                    row.append(col)
                } else if (key === 'чай') {
                    row = document.createElement('tr')
                    table.append(row)

                    col = document.createElement('td')
                    col.innerText = `На ${key.toUpperCase()} редюсеру-трудяге`
                    col.style.cssText = `
                min-width: 150px;
                font-size: 1.5em;
                padding: 5px 10px;
                text-align: left`
                    row.append(col)

                    col = document.createElement('td')
                    col.innerText = `${values}`
                    col.style.cssText = `
                font-size: 1.5em;
                text-align: center;`
                    row.append(col)
                } else {
                    // рисуем строку заголовков
                    row = document.createElement('tr')
                    table.append(row)

                    col = document.createElement('td')
                    col.innerText = `${key.toUpperCase()}`
                    col.style.cssText = `
                min-width: 150px;
                font-size: 2em;
                padding: 5px 10px;
                text-align: left`
                    row.append(col)

                    // рисуем строки значений для товаров
                    for (const name of params) {
                        col = document.createElement('td')
                        col.innerText = `${(Object.keys(values)).includes(name) ? values[name] : ''}`
                        col.style.cssText = `
                    font-size: 1.5em;
                    text-align: center`
                        row.append(col)
                    }
                }
            }
            return table
        }
        createTable()

        // start test in console.log
        store.subscribe(() => console.log(store.getState()))

        // create divWindow
        const divWindow = document.createElement('div')
        divWindow.style.cssText = `
    min-width: 700px;
    width: 50%;
    padding: 10px;
    margin-top: 30px;`
        document.body.append(divWindow)

        // create divWindow title
        const divWindowitle = document.createElement('h2')
        divWindowitle.innerText = 'Покупка в ларьке'
        divWindowitle.style.cssText = `
    text-align: center;`
        divWindow.append(divWindowitle)


        // create inputAmount
        const inputAmount = document.createElement('input')
        inputAmount.type = 'number'
        inputAmount.min = 0
        inputAmount.placeholder = 'Количество товара'
        divWindow.append(inputAmount)

        // ceate inputMoney
        const inputMoney = document.createElement('input')
        inputMoney.type = 'number'
        inputMoney.min = 0
        inputMoney.placeholder = 'Сумма, которую отдаете'
        divWindow.append(inputMoney)

        let selectProduct
        createListProduct = () => {
            // create selectProduct
            selectProduct = document.createElement('select')
            divWindow.insertBefore(selectProduct, inputMoney)

            for (let key of Object.keys(store.getState())) {
                if (key !== 'касса' && key !== 'чай') {
                    let optionInput = document.createElement('option')
                    optionInput.innerText = `${key}`
                    selectProduct.append(optionInput)
                }
            }
            return selectProduct
        }
        createListProduct()

        // create buyButton 
        const buyButton = document.createElement('button')
        buyButton.innerText = 'Купить'
        divWindow.append(buyButton)

        // create add div
        const divAdd = document.createElement('div')
        divAdd.style.cssText = `
        min-width: 700px;
        width: 50%;
        margin-top: 40px;`
        document.body.append(divAdd)

        // create add div title
        const divAddTitle = document.createElement('h2')
        divAddTitle.innerText = 'Пополнение ларька'
        divAddTitle.style.cssText = `
    text-align: center;`
        divAdd.append(divAddTitle)

        // create inputAddProduct
        const inputAddProduct = document.createElement('input')
        inputAddProduct.type = 'text'
        inputAddProduct.placeholder = 'Введите имя продукта'
        divAdd.append(inputAddProduct)

        // create inputAddAmount
        const inputAddAmount = document.createElement('input')
        inputAddAmount.type = 'number'
        inputAddAmount.min = 0
        inputAddAmount.placeholder = 'Введите количество продукта'
        divAdd.append(inputAddAmount)

        // create inputAddPrice
        const inputAddPrice = document.createElement('input')
        inputAddPrice.type = 'number'
        inputAddPrice.min = 0
        inputAddPrice.placeholder = 'Введите цену продукта'
        divAdd.append(inputAddPrice)

        // create addProductButton
        const addProductButton = document.createElement('button')
        addProductButton.innerText = 'Добавить продукт'
        divAdd.append(addProductButton)

        // mistake alert
        addProductButton.onclick = () => {
            if ((+inputAddAmount.value * +inputAddPrice.value) > store.getState().касса) {
                alert('В кассе нет столько денег! Давай торговаться?')
            }
        }

        // start addProductButton
        addProductButton.addEventListener('click', () => store.dispatch({ type: 'ДОБАВИТЬ', ШО_ДОБАВИТЬ: inputAddProduct.value, СКОКА_ДОБАВИТЬ: +inputAddAmount.value, ЦЕНА_ДОБАВИТЬ: +inputAddPrice.value }))

        // mistake alert
        buyButton.onclick = () => {
            if (+inputAmount.value > store.getState()[selectProduct.value].amount) {
                alert(`Количество товара, который вы хотите купить, больше, чем наличие на складе! На складе ${store.getState()[selectProduct.value].amount} единиц ${selectProduct.value}`)
            } else if (+inputMoney.value < (+inputAmount.value * store.getState()[selectProduct.value].price)) {
                alert(`Вы даете ${inputMoney.value}. А нужно ${+inputAmount.value * store.getState()[selectProduct.value].price}. Добавьте ${(+inputAmount.value * store.getState()[selectProduct.value].price) - +inputMoney.value}`)
            }
        }

        // start buyButton
        buyButton.addEventListener('click', () => store.dispatch({ type: 'КУПИТЬ', ШО: selectProduct.value, СКОКА: +inputAmount.value, БАБЛО: +inputMoney.value }))

        // Relaod table with new datas
        store.subscribe(() => {
            table.remove(),
                selectProduct.remove(),
                createTable(),
                createListProduct()

        })
    }
}



// Password
// Напишите функцию конструктор Password, которая будет в родительском элементе создавать поле ввода для пароля и кнопку / иконку / чекбокс, который будет переключать режим просмотра пароля в поле ввода. (видимый пароль или нет, input type = 'text' или же input type = 'password')

// Параметры:
//      parent - родительский элемент
//      open - стартовое состояние

// Методы:
//      setValue / getValue - задают / читают значения
//      setOpen / getOpen - задают / читают открытость текста в поле ввода

// Колбэки(функции обратного вызова, который возможно, будут заданы снаружи конструктора):
//      onChange - запускается по событию oninput в поле ввода, передает текст в колбэк
//      onOpenChange - запускается по изменению состояния открытости пароля
{
    function Password(parent, open) {
        // create filed for password
        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)
        })
    }

    let p = new Password(document.body, true)

    p.onChange = data => console.log('onChange: ', data)
    p.onOpenChange = open => console.log('onOpenChange: ', open)

    p.setValue('qwerty')
    console.log(p.getValue())

    p.setOpen(false)
    console.log(p.getOpen())
}



// LoginForm
// С помощью предыдущего кода Password сделайте форму логина, кнопка в которой будет активна только если и login и пароль не пусты.   
// WARNING! "С помощью предыдущего кода" значит что в коде формы логина вы используете объект, сконструированный конструктором Password - const password = new Password(........)
{
    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')
    document.body.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 = 'submit'
    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
}



// LoginForm Constructor
// оформите предыдущую задачу как функцию - конструктор.Продумайте и предусмотрите геттеры, сеттеры и колбэки.
{
    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 = 'submit'
        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
    }

    const loginForm = new LoginForm(document.body)

    loginForm.setPasswordValue('1q2w3e')
    console.log(loginForm.getPasswordValue())

    loginForm.setLoginValue('login')
    console.log(loginForm.getLoginValue())

    loginForm.setPasswordOpen(false)
    console.log(loginForm.getPasswordOpen())

    loginForm.onOpenChange(open => console.log(open))
}



// Password Verify - almost done
// С помощью Password сделайте пару инпутов, которые проверяют введеный пароль(в двух полях ввода) на совпадение.Подсвечивайте поля красным цветом / бордером когда пароли не совпадают При открытом пароле в первом поле ввода(которое реализуется с помощью объекта класса Password второе поле вводы должно пропадать с экрана Таким образом:
//     Когда Password в скрытом режиме - появляется второй инпут(<input type='password'>) с паролем в скрытом режиме
//     Когда Password в открытом режиме - второй инпут пропадает
{
    function Password(parent, open) {
        // create filed for password
        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)
        })

        // set background color
        this.setBackground = (value) => {
            inputPassword.style.backgroundColor = value
        }
    }

    function Checher(parent) {
        const passwordVerifyDiv = document.createElement('div')
        passwordVerifyDiv.style.backgroundColor = 'transparent'
        parent.append(passwordVerifyDiv)

        const mainDiv = document.createElement('div')
        passwordVerifyDiv.append(mainDiv)

        let main = new Password(mainDiv, true)

        const checkedDiv = document.createElement('div')
        checkedDiv.style.display = 'block'
        passwordVerifyDiv.append(checkedDiv)

        let checked = new Password(checkedDiv, true)

        main.onOpenChange = open => {
            !open ? checkedDiv.style.display = 'block' : checkedDiv.style.display = 'none'
        }

        function checker() {
            if (main.getValue() !== checked.getValue()) {
                main.setBackground('#FFAAAA')
                checked.setBackground('#FFAAAA')
            } else {
                main.setBackground('transparent')
                checked.setBackground('transparent')
            }
            return main.setBackground, checked.setBackground
        }
        checker()

        main.onChange = checked.onChange = checker
    }

    const checker = new Checher(document.body)
}