/*Arrow to Functions
Переведите любые пять заданий из предыдущего ДЗ по функциям в синтаксис function*/

/* 1. Calc Func
Вспомните первое ДЗ по Javascript, в котором вы делали всякие расчеты используя код на Javascript. Оформите это как функцию:
найдите все входящие данные, сделайте из них параметры
найдите переменную с результатом расчетов и сделайте так, что бы ваша функция возвращала этот результат.
Если результатов несколько, создайте объект из этих результатов и верните его. */

{
    function bikeRentCalculator(bikes, bikesCategory, bikesCost, timeRent) {
        let costResult = bikes * bikesCost * timeRent;
        return {
            bikes,
            bikesCategory,
            bikesCost,
            timeRent,
            costResult,
        }
    }
}

//2. Temperature
//Оформите Temperature как функцию, в которую параметром передается температура в одной системе, а возвращается в другой. Никаких prompt и console.log в коде быть не должно, если вы хотите в дальнейшем пользоваться этой функцией где угодно в коде удобно. Нужен ли блок кода в функции для решения этой задачи?

{
    function temperatureCtoF(c) {
        return c * 9 / 5 + 32
    }
}

/*3. Flats
Оформите Number: flats как функцию. Продумайте достаточное количество параметров для решения задачи. Функция должна возвращать объект вида {entrance, floor}, где entrance - номер падика, floor - номер этажа на котором находится квартира.*/

{
    function entranceAndFlor(apartmentNumber, houseFloors, apartmentОnFloor) {
        const apartmentOnFrontDoor = houseFloors * apartmentОnFloor;
        const apartmentNumberInFrontDoor = (apartmentNumber - 1) % apartmentOnFrontDoor;
        const floor = Math.floor(apartmentNumberInFrontDoor / apartmentОnFloor) + 1;
        const entrance = Math.ceil(apartmentNumber / apartmentOnFrontDoor);

        return result = {
            entrance,
            floor
        }
    }

    console.log(entranceAndFlor(36, 9, 4))
}

/*4. New line
Оформите задание String: new line как функцию с параметром-строкой. Функция должна возвращать строку с настоящими переносами. */

{
    function stringNewline(str) {
        return str.split('\\n').join('\n')
    }
    console.log(stringNewline('sdf\n\nsdf\nsdf'))
}

/*5. For Multiply Table
Выведите таблицу умножения 5x5 из задания Multiply table в таблицу, используя вложенные for .... of и document.write
Сделайте черезстрочную подсветку - задавайте четным строкам один цвет фона, нечетным - другой*/

{
    const arr = [

        [0, 0, 0, 0, 0, 0],
        [0, 1, 2, 3, 4, 5],
        [0, 2, 4, 6, 8, 10],
        [0, 3, 6, 9, 12, 15],
        [0, 4, 8, 12, 16, 20],
        [0, 5, 10, 15, 20, 25]

    ];


    function arrToHtml(arr) {

        let str = "<table>"
        let i = 1

        for (let tr of arr) {

            if (i++ % 2 === 0) {
                str += '<tr style="background-color: grey;">'
            } else {
                str += "<tr>"
            }

            for (let td of tr) {
                str += "<td>" + td + "</td>"
            }
            str += "</tr>"
        }

        str += "</table>"
        return (str)
    }

    console.log(arrToHtml(arr))
}

/*createPerson
Создайте функцию createPerson, которая принимает два параметра: name и surname, и возвращает объект с ключами name, surname, getFullName. getFullName должна быть функцией, которая работает с объектом через this, а так же готова к тому, что в объекте в последствии добавить ключ fatherName*/
{
    const a = createPerson("Вася", "Пупкин")
    const b = createPerson("Анна", "Иванова")
    const c = createPerson("Елизавета", "Петрова")

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

    function createPerson(name, surname) {
        return {
            name,
            surname,
            getFullName() {
                return `${this.name} ${this.fatherName || ""} ${this.surname}`
            }
        }
    }
}

/*createPersonClosure
Задание в целом, аналогично предыдущему, однако, в объект заносить name, surname, fatherName и age не нужно. name и surname должны быть параметрами, переменные age и fatherName объявите через let в теле createPersonClosure. Внутри createPersonClosure объявите следующие функции:
getName
getSurname
getFatherName
getAge
getFullName
Эти функции должны возвращать переменные, объявленные в функции createPersonClosure
Следующие функции:
setName
setSurname
setFatherName
setAge
setFullName
должны принимать один параметр (newName, newSurname и т.п.), проверять его на корректность и менять значение переменных, объявленных внутри createPersonClosure. Проверки на корректность:
имя, фамилия, отчество должно быть строкой с большой буквы
возраст должен быть числом от 0 до 100.
Если проверка на корректность не пройдена, функция не должна менять соответстующую переменную.
Функция setFullName должна разбивать строку по пробелам и заносить части строки в surname, name и fatherName
Все функции set должны возвращать то значение, которое по итогу попало во внутренюю переменную. То есть если новое значение некорректно, то функция возвращает старое значение
В объекте-результате createPersonClosure должны быть только эти 10 функций (геттеров и сеттеров). В коде функций this не используется
const a = createPersonClosure("Вася", "Пупкин")
const b = createPersonClosure("Анна", "Иванова")
console.log(a.getName())
a.setAge(15)
a.setAge(150) //не работает

b.setFullName("Петрова Анна Николаевна")
console.log(b.getFatherName()) //Николаевна*/

{
    function createPersonClosure(name, surname) {
        let age
        let fatherName

        return {

            getName() { return name },
            getSurname() { return surname },
            getFatherName() { return fatherName },
            getAge() { return age },
            getFullName() { return `${name} ${fatherName || ""} ${surname}` },
            setName(newName) { if (newName[0] === newName[0].toUpperCase()) name = newName; return name },
            setSurname(newSurname) { if (newSurname[0] === newSurname[0].toUpperCase()) surname = newSurname; return surname },
            setFatherName(newFatherName) { if (newFatherName[0] === newFatherName[0].toUpperCase()) fatherName = newFatherName; return fatherName },
            setAge(newAge) { if (newAge >= 0 && newAge <= 100) age = newAge; return age },
            setFullName(newFullName) {
                let arr = newFullName.split(" ")
                if (arr[0][0] === arr[0][0].toUpperCase() &&
                    arr[1][0] === arr[1][0].toUpperCase() &&
                    arr[2][0] === arr[2][0].toUpperCase()) {
                    surname = arr[0]
                    name = arr[1]
                    fatherName = arr[2]
                } return this.getFullName()
            }
        }
    }

    const a = createPersonClosure("Вася", "Пупкин")
    const b = createPersonClosure("Анна", "Иванова")
    console.log(a.getName())
    console.log(a.setAge(15))
    console.log(a.getAge())
    console.log(a.setAge(150)) //не работает
    console.log(a.getAge())

    console.log(b.setFullName("Петрова Анна Николаевна"))
    console.log(b.getFatherName()) //Николаевна*/
}

/*createPersonClosureDestruct
Сделайте набор параметров функции из предыдущего задания объектом, используйте деструктуризацию для извлечения параметров.
Задайте значения по умолчанию
const a = createPersonClosureDestruct(createPerson("Вася Пупкин"))
const b = createPersonClosureDestruct({name: 'Николай', age: 75})*/
{
    function createPersonClosureDestruct({ name = "Анон", surname = "Анонов", fatherName = "Анонович", age = "х.з." } = {}) {
        const obj = {
            name,
            surname,
            fatherName,
            age,
        }
        return obj
    }

    function createPerson(name, surname) {
        return {
            name,
            surname,
            getFullName() {
                return `${this.name} ${this.fatherName || ""} ${this.surname}`
            }
        }
    }
    const a = createPersonClosureDestruct(createPerson("Вася Пупкин")) // не очень понятно что должно получится в задании. В createPerson мы принимали два параметра соответвенно если так передать оба слова залетят в name. надеюсь так и задумано или я где-то не понял условие...
    const b = createPersonClosureDestruct({ name: 'Николай', age: 75 })
    console.log(createPerson("Вася Пупкин"))
    console.log(a)
    console.log(b)
}

/*isSorted
Напишите функцию isSorted, которая принимает набор параметров любого размера, и возвращает true, когда все параметры - это числа, и каждое из них больше предыдущего параметра.*/

{
    function isSorted(...arr) {
        console.log(arr)
        if (typeof arr[0] !== "number" || isNaN(arr[0])) return false
        let previousItem = arr[0]
        for(let i = 1; i<arr.length; i++){
            if (typeof arr[i] !== "number" || isNaN(arr[i]) || previousItem > arr[i] ) return false;
            previousItem = arr[i]
        }
        return true
    }
    console.log( isSorted(1,5,{},15,7,6,5) )
    console.log( isSorted(1,5,3,15,7,6,5) )
    console.log( isSorted(1,5,[7],15,7,6,5) )
    console.log( isSorted(1,NaN,7,15,20,25,30) )
    console.log( isSorted(1,5,7,15,20,25,30) )
}

/*Test isSorted
Используя циклический ввод в массив (задание array fill), обеспечьте ввод данных для isSorted*/

/*array fill
Создайте пустой массив и добавляйте в него элементы, пока пользователь не нажмет Отмена в очередном prompt. Используйте push для удобства: push*/

{

    function isSorted(arr) {
        console.log(arr)
        if (typeof arr[0] !== "number" || isNaN(arr[0])) return false
        let previousItem = arr[0]
        for (let i = 1; i < arr.length; i++) {
            if (typeof arr[i] !== "number" || isNaN(arr[i]) || previousItem > arr[i]) return false;
            previousItem = arr[i]
        }
        return true
    }


    function isSortedArrValue() {
        const arr = []
        let i
        while ((i = prompt('добавить в массив или отмена для проверки isSorted')) !== null) {
            if (i !== "") arr.push(+i)
        }
        alert('вы наклацали ' + arr)
        return arr
    }

    console.log(isSorted(isSortedArrValue()))
}

/* personForm
Напишите функцию, которая принимает два параметра: родительский DOM-элемент и объект-результат работы createPersonClosure (или createPersonClosureDestruct, результаты у обоих этих функций одинаковые) и рисует форму, которая позволяет редактировать данные о персоне.
В начале работы personForm создает 5 полей ввода (имя, фамилия, отчество, возраст, ФИО) в родительском DOM-элементе и устанавливает туда значения, прочитанные с помощью getName, getSurname и т.д.
По событию oninput в любом из полей ввода нужно запускать соответствующий set..... Например при изменении поля ввода имени должен запускаться setName(какой-то инпут.value). Функции set... возвращают значение, и его нужно занести обратно в input. Таким образом в полях ввода невозможно будет ввести некорректные значения (например возраст не сможет выйти за пределы 0-100 лет)
const b = createPersonClosure("Анна", "Иванова")
b.setAge(15)
b.setFullName("Петрова Анна Николаевна")
*/

{
    function createPersonClosure(name, surname) {
        let age
        let fatherName

        return {

            getName() { return name },
            getSurname() { return surname },
            getFatherName() { return fatherName },
            getAge() { return age },
            getFullName() {
                return `${name} ${fatherName || ""} ${surname}`            
            },
            setName(newName) { 
                if (newName === "") {name = newName; return name}
                if (newName[0] === newName[0].toUpperCase() && newName[0] !== " ") name = newName; return name },
            setSurname(newSurname) { 
                if (newSurname === "") {surname = newSurname; return surname}
                if (newSurname[0] === newSurname[0].toUpperCase() && newSurname[0] !== " ") surname = newSurname; return surname },
            setFatherName(newFatherName) {
                if (newFatherName === "") {fatherName = newFatherName; return fatherName}
                if (newFatherName[0] === newFatherName[0].toUpperCase() && newFatherName[0] !== " ") fatherName = newFatherName; return fatherName },
            setAge(newAge) { if (newAge >= 0 && newAge <= 100) age = newAge; return age },
            setFullName(newFullName) {

                
                let arr = newFullName.split(" ")
                if (arr[2] !== undefined){
                    name = arr[0]
                    fatherName = arr[1]
                    surname = arr[2]
                    return this.getFullName()
                }else if (arr[1] !== undefined){
                    name = arr[0]
                    fatherName = arr[1]
                    surname = ""
                    return this.getFullName()
                }else if(arr[0] !== undefined){
                    name = arr[0]
                    fatherName = ""
                    surname = ""
                    //return this.getFullName()
                }
            }
        }
    }

    function personForm(parent, person){

        //насоздавать инпутов (5 штук)
        let inputName = document.createElement('input')
        inputName.value = person.getName()
        let inputFatherName = document.createElement('input')
        inputFatherName.value = person.getFatherName()
        let inputSurname = document.createElement('input')
        inputSurname.value = person.getSurname()
        let inputAge = document.createElement('input')
        inputAge.value = person.getAge()
        inputAge.type = "number"
        let inputFullName = document.createElement('input')
        inputFullName.value = person.getFullName()

        //надобавлять их в parent
        parent.append(inputName)
        parent.append(inputFatherName),
        parent.append(inputSurname)
        parent.append(inputAge)
        parent.append(inputFullName)

        //навесить каждому из них обработчик события типа nameInput.oninput = () => {
            //тут пытаемся менять person используя person.setName. Текст в инпуте должен стать таким, который вернет setName
        //}
        inputName.oninput = () => {
           inputName.value = person.setName(inputName.value)
           inputFullName.value = person.getFullName()
        }
        inputSurname.oninput = () => {
            inputSurname.value = person.setSurname(inputSurname.value)
            inputFullName.value = person.getFullName()
        }
        inputFatherName.oninput = () => {
            inputFatherName.value = person.setFatherName(inputFatherName.value)
            inputFullName.value = person.getFullName()
        }
        inputAge.oninput = () => {
            inputAge.value = person.setAge(inputAge.value)
        }
        inputFullName.oninput = () => {
            inputFullName.value = person.setFullName(inputFullName.value)
            inputName.value = person.getName()
            inputSurname.value = person.getSurname()
            inputFatherName.value = person.getFatherName()

        }
    }

    const b = createPersonClosure("Анна", "Иванова")
    b.setAge(15)
    b.setFullName("Анна Николаевна Петрова")
    personForm(document.body, b)
}

/*getSetForm
Сделайте функцию, которая решает предыдущую задачу универсально, то есть для любого объекта, в котором есть набор функций get... и set.... Кода станет меньше, гибкости больше, ведь в предыдущем задании много копипасты (x5)*/

{
    function createPersonClosure(name, surname) {
        let age
        let fatherName

        return {

            getName() { return name },
            getSurname() { return surname },
            getFatherName() { return fatherName },
            getAge() { return age },
            getFullName() {
                return `${name} ${fatherName || ""} ${surname}`            
            },
            setName(newName) { 
                if (newName === "") {name = newName; return name}
                if (newName[0] === newName[0].toUpperCase() && newName[0] !== " ") name = newName; return name },
            setSurname(newSurname) { 
                if (newSurname === "") {surname = newSurname; return surname}
                if (newSurname[0] === newSurname[0].toUpperCase() && newSurname[0] !== " ") surname = newSurname; return surname },
            setFatherName(newFatherName) {
                if (newFatherName === "") {fatherName = newFatherName; return fatherName}
                if (newFatherName[0] === newFatherName[0].toUpperCase() && newFatherName[0] !== " ") fatherName = newFatherName; return fatherName },
            setAge(newAge) { if (newAge >= 0 && newAge <= 100) age = newAge; return age },
            setFullName(newFullName) {

                
                let arr = newFullName.split(" ")
                if (arr[2] !== undefined){
                    name = arr[0]
                    fatherName = arr[1]
                    surname = arr[2]
                    return this.getFullName()
                }else if (arr[1] !== undefined){
                    name = arr[0]
                    fatherName = arr[1]
                    surname = ""
                    return this.getFullName()
                }else if(arr[0] !== undefined){
                    name = arr[0]
                    fatherName = ""
                    surname = ""
                    return this.getFullName()
                }
            }
        }
    }


    let car;
    {
        let brand = 'BMW', model = 'X5', volume = 2
        car = {
            getBrand(){
                return brand
            },
            setBrand(newBrand){
                if (newBrand && typeof newBrand === 'string'){
                    brand = newBrand
                }
                return brand
            },
            
            getModel(){
                return model
            },
            setModel(newModel){
                if (newModel && typeof newModel === 'string'){
                    model = newModel
                }
                return model
            },
            
            getVolume(){
                return volume
            },
            setVolume(newVolume){
                newVolume = +newVolume
                if (newVolume && newVolume > 0 && newVolume < 20){
                    volume = newVolume
                }
                return volume
            },
            
            getTax(){
                return volume * 100
            }
        }
    }

    function getSetForm(parent, getSet){
        const inputs = {} //реестр
        
        const updateInputs = (inputs, getSet) => { 
            
            //функция обновления полей ввода согласно всяким get....
            //тут должен быть перебор

            for (const inputKey in inputs){
                let key = 'get' + inputKey
                if (key in getSet) inputs[inputKey].value = getSet[key]()
            }
        }
        
        for (const getSetName in getSet){
            const getOrSet = getSetName[0] + getSetName[1] + getSetName[2]
            const [,,,...arr] = getSetName
            fieldName = arr.join('')
            const setKey    = `set` + fieldName
            const getKey    = `get` + fieldName
            
            if ( !(fieldName in inputs)){
                inputs[fieldName] = document.createElement('input')
            }
            if (!(setKey in getSet)) {
                inputs[fieldName].disabled = true
            }
            inputs[fieldName].placeholder = fieldName
            if (getSet[getKey]() !== undefined) {inputs[fieldName].value = getSet[getKey]()}
            //const typeValue = typeof getSet[getSetName]()
            const typeValue = typeof getSet[getKey]()
            let typeHtml
            if (typeValue === "number") typeHtml = "number";
            if (typeValue === "string") typeHtml = "text";
            if (typeValue === "boolean") typeHtml = "checkbox";
            inputs[fieldName].type = typeHtml
            
            const element = inputs[fieldName] 
            element.oninput = () => {
                
                
                element.value = getSet[setKey](element.value)
                console.log(element.value)
                //console.log(inputs[fieldName].value)
                //console.log(getSet[setKey])
                updateInputs(inputs, getSet)
            }
            //допишите тут все шо надо, и не только тут
            //console.log(inputs[fieldName].value)
            //console.log(getSet[setKey])//(inputs[fieldName].value))
        }
        console.log(inputs)
        for (key in inputs){
            parent.append(inputs[key])
        }
    }

    let b = createPersonClosure('Анон', "Анонов")
    getSetForm(document.body, car)
    getSetForm(document.body, b)
    console.log(b)
    console.log(car)
}