/*function jsonPost(url, data)
{
    return new Promise((resolve, reject) => {
        var x = new XMLHttpRequest();   
        x.onerror = () => reject(new Error('jsonPost failed'))
        //x.setRequestHeader('Content-Type', 'application/json');
        x.open("POST", url, true);
        x.send(JSON.stringify(data))

        x.onreadystatechange = () => {
            if (x.readyState == XMLHttpRequest.DONE && x.status == 200){
                resolve(JSON.parse(x.responseText))
            }
            else if (x.status != 200){
                reject(new Error('status is not 200'))
            }
        }
    })
}*/

async function jsonPost(url, data){
  try {
    let response = await fetch(url, {
      method: 'POST',
      body: JSON.stringify(data)
      
  })
      
      if (response.ok) {
        
        let json = await response.json()        
        
        return json}
  } catch (error) {
    console.log('ошибка: ' + error) //ловим ошибки
  }
}


//событие по кнопке SEND с проверкой заполненности полей
sendButton.onclick = sendAndCheck

async function sendMessage(nick, message) {
  if (nick && message) {
    jsonPost("http://students.a-level.com.ua:10012", { func: 'addMessage', nick, message })
  }
}

async function getMessages (id) {
  const res = await jsonPost("http://students.a-level.com.ua:10012", { func: "getMessages", messageId: id}).then(res => res)

  nextMessageId = res.nextMessageId
  for(const msg of res.data){
    const msgDiv = document.createElement('div')
    chat.prepend(msgDiv)

    const userNick = document.createElement('span')
    msgDiv.append(userNick)
    userNick.innerText = msg.nick + ': '
    userNick.classList.add('nick')

    const userMessage = document.createElement('span')
    msgDiv.append(userMessage)
    userMessage.innerText = msg.message

    const timeMessage = document.createElement('span')
    msgDiv.prepend(timeMessage)
    const msgTime = new Date(msg.timestamp)
  
    let timeFormatHhMmSs = ''
    timeFormatHhMmSs += msgTime.getFullYear() + '.'
    if (msgTime.getMonth() < 9) timeFormatHhMmSs += '0' + (msgTime.getMonth()+1) + '.'
    else timeFormatHhMmSs += (msgTime.getMonth()+1) + '.'
    if (msgTime.getDate() < 10) timeFormatHhMmSs += '0' + msgTime.getDate() + ' '
    else timeFormatHhMmSs += msgTime.getDate() + ' '
    if (msgTime.getHours() < 10) timeFormatHhMmSs += '0' + msgTime.getHours() + ':'
    else timeFormatHhMmSs += msgTime.getHours() + ':'
    if (msgTime.getMinutes() < 10) timeFormatHhMmSs += '0' + msgTime.getMinutes() + ':'
    else timeFormatHhMmSs += msgTime.getMinutes() + ':'
    if (msgTime.getSeconds() < 10) timeFormatHhMmSs += '0' + msgTime.getSeconds()
    else timeFormatHhMmSs += msgTime.getSeconds()
    timeMessage.innerText = timeFormatHhMmSs
    
  }

}

async function sendAndCheck(){
  await sendMessage(userName.value, userMessage.value)
  getMessages (nextMessageId)
}

let nextMessageId = 0
//первоначальная загрузка и вывод на экран сообщений из чата
//getMessages (nextMessageId)


//каждые две секунды проверяем новые сообщения, если есть, добавляем их к тем что уже на экране
//setInterval( () => getMessages (nextMessageId), 2000 )

function delay(ms){ //промисифицированная функция для создания промиса, который резолвится через определенное время
  //функция-исполнитель, принимает два параметра - функции для передачи промису результата работы
  function executor(fulfill, reject){  //reject объявлен для вида.
      setTimeout(() => fulfill(ms), ms) //setTimeout запустит функцию, которая запустит fulfill через ms миллисекунд. Результатом промиса будет время задержки
  }
  
  //возврщаем новый промис, передав в него executor. Промис тут же его запускает, передав в него колбэки для управления состоянием
  return new Promise(executor) 
}

async function checkLoop() {
 while(true) {
  getMessages (nextMessageId)
  await delay(2000)
  console.log('2сек')
 }
}

checkLoop()

/*SWAPI Links
Напишите промисифицированную функцию, которая принимать параметром ссылку на swapi.dev (например, https://swapi.dev/api/people/20) и скачивать всю информацию по ссылке, включая вложенные ссылки. Все ссылки внутри скачанного объекта должны заменяться на скачанные объекты. Полученный общий объект должен стать результатом промиса, который возвращает функция.
Например, ссылка, приведенная выше позволяет информацию о Йода Мастере скачать:

Ваша функция должна перебрать весь объект, найти там ссылки и массивы со ссылками, скачать эти ссылки и сложить это всё в общий объект, заместив строки со ссылками. Получится что-то такое:

Ваша функция может быть обычной (с цепочкой .then) или асинхронной, по желанию. Главное-вовремя зарезолвить промис-результат функции. Сделайте запросы по вложенным в объект ссылкам параллельно. Для проверки корректности работы функции - выводите в консоль JSON-строку, вместо оригинального объекта. Это позволит убедиться в том, что ваша функция резолвит промис именно тогда, когда все данные по вложенным ссылкам скачаны:
swapiLinks("https://swapi.dev/api/people/20/")
    .then(yodaWithLinks => console.log(JSON.stringify(yodaWithLinks, null, 4)))
Если же вы просто выведете объект (console.log(yodaWithLinks)), то за счет ссылочности объектов в Javascript, в него можно добавить что-то уже после вывода. Раскрыв этот объект при отладке в консоли спустя пару секунд после вывода, вы увидите что всё ок. Однако это не значит, что все реально ОК на момент работы console.log.
Вывод JSON покажет вам правду - состояние объекта на момент резолва промиса-результата вашей функции.
В теле функции new Promise не нужен.*/

swapiLinks("https://swapi.dev/api/people/20/")
    .then(yodaWithLinks => console.log(JSON.stringify(yodaWithLinks, null, 4)))

async function downloadLink(link){
  let jsonObj = await fetch(link).then(res => res.json())
  return jsonObj
}

async function swapiLinks(link) {
 
  const allP = [];
  try {
    let jsonObj = await downloadLink(link)
    for (const key in jsonObj){
      let regexp = /^\s*https?:\/\/./i; //тут проверяем является ли значение ссылкой
      let value = jsonObj[key];
      
      if (regexp.test(value) && typeof value === "string") { //если значение ссылка но не массив
         allP.push(downloadLink(value).then(resultObj => jsonObj[key] = resultObj))
      
      } else if (Array.isArray(value)) {
         
        allP.push(Promise.all(
         value.map(downloadLink)
        ).then(
         resultObj => {
           jsonObj[key] = resultObj
         }
        ))
      }
    }
    return Promise.all(allP)
     .then(() => jsonObj)
  } catch (error) {
    console.log("Ошибка: " + error)
  }
   
}

/*domEventPromise
Реализуйте промисифицированную функцию, которая резолвит промис по событию в DOM:

function domEventPromise(element, eventName){
    function executor(resolve){
        //happy hacking
    }
    return new Promise(executor)
}


domEventPromise(knopka, 'click').then( e => console.log('event click happens', e))

Функция должна:
используя addEventListener повесить свой обработчик события на DOM element событие eventName
по событию зарезолвить промис отдав в качестве результата объект события
убрать обработчик с DOM-элемента, используя removeEventListener.
Убедитесь, что действительно убираете обработчик после резолва промиса. Он больше не нужен.*/


function domEventPromise(element, eventName){
  function executor(resolve){
      //happy hacking
      function myEvent(event) {
        element.removeEventListener(eventName, myEvent)
        resolve(event)
      }
    
    
      element.addEventListener(eventName, myEvent)
     
  }
  return new Promise(executor)
}
let div = document.createElement('div')
document.body.append(div)
div.style.width = '100px'
div.style.height = '100px'
div.style.backgroundColor = 'red'
domEventPromise(div, 'click').then( e => console.log('event click happens', e))




