// 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 improved
// Расширить функцию отображения:
// Если одно из полей строка или массив.
// Если строки или строка содержат в себе https://swapi.dev/api/
// То выводить вместо текста строки кнопку, при нажатии на которую:
// делается fetch данных по этой ссылке
// функция отображения запускает сама себя(рекурсивно) для отображения новых данных в том же элементе.
fetch_basic: {
  fetch('https://swapi.dev/api/people/1/')
    .then(res => res.json())
    .then(luke => {
      // console.log(luke);
      displayObjAsTable(document.body, luke);
    })

  function displayObjAsTable(domElement, jsonElement, elemForRemoval) {
    let table = document.createElement('table');
    table.border = 1;
    elemForRemoval?.remove();
    domElement.append(table);
    Object.keys(jsonElement).forEach(key => {
      let tr = document.createElement('tr');
      table.append(tr);
      let keyTd = document.createElement('td');
      keyTd.innerText = key;
      tr.append(keyTd);
      let valueTd = document.createElement('td');
      if (typeof jsonElement[key] == 'string' && jsonElement[key].includes('https://swapi.dev/api/')) {
        addButton(jsonElement[key], valueTd);
      } else if (Array.isArray(jsonElement[key])) {
        jsonElement[key].forEach((el) => {
          if (typeof el == 'string' && el.includes('https://swapi.dev/api/')) {
            addButton(el, valueTd);
          }
        });
      } else {
        valueTd.innerText = jsonElement[key];
      }
      tr.append(valueTd);
    });
  }
  function addButton(value, valueTd) {
    let button = document.createElement('button');
    button.innerText = 'Get ' + value.split('api/')[1];
    button.addEventListener('click', () => {
      fetch(value)
        .then(res => res.json())
        .then(data => {
          displayObjAsTable(valueTd, data, button);
        })
    });
    valueTd.append(button);
  }
}

// race
// Используя Promise.race запустите запрос на API (swapi.dev) параллельно с delay. По результату определите,
// что было быстрее, запрос по сети, или определенный интервал времени. Подберите параметр delay так, что бы
// результат был неизвестен изначально, и при многократных запусках быстрее был то delay, то myfetch.
race: {
  function delay(ms) {
    function executor(fulfill, reject) {
      setTimeout(() => fulfill(ms), ms);
    }
    return new Promise(executor);
  }
  let myfetch = fetch('https://swapi.dev/api/people/2/');
  Promise.race([myfetch, delay(100)]).then((value) => {
    console.log(value);
  });
}

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

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

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

// Promisify: LoginForm
// Промисифицируйте конструктор LoginForm. В промисифицированную функцию передается DOM-элемент - родитель для
// формы, В колбэке, предназначенном для получения логина и пароля в момент нажатия кнопки "Login...", который
// вы назначаете в объекте LoginForm, зарезолвите промис. Результатом промиса должен быть объект с ключами
// login и password, ключи должны содержать значения полей ввода.
login_form: {
  function LoginForm(parent) {
    let form = document.createElement('form');
    parent.append(form);
    let loginLabel = document.createElement('label');
    loginLabel.innerText = 'Login: ';
    form.append(loginLabel);
    let login = new Login(form);
    let passwordLabel = document.createElement('label');
    passwordLabel.innerText = 'Password: ';
    form.append(passwordLabel);
    let password = new Password(form, false);
    let submit = document.createElement('button');
    submit.innerText = 'Submit';
    form.append(submit);
    this.validateForm = () => {
      if (login.getValue() == '' || password.getValue() == '') {
        submit.disabled = true;
      } else {
        submit.disabled = false;
        if (this.onValidForm) {
          this.onValidForm();
        }
      }
    }
    submit.addEventListener('click', (e) => {
      e.preventDefault();
      if (this.onSubmitForm) {
        this.onSubmitForm();
      }
    });
    this.getLoginValue = () => {
      return login.getValue();
    }
    this.setLoginValue = (value) => {
      login.setValue(value);
    }
    this.getPasswordValue = () => {
      return password.getValue();
    }
    this.setPasswordValue = (value) => {
      password.setValue(value);
    }
    this.validateForm();
    login.onChange = this.validateForm;
    password.onChange = this.validateForm;
  }

  function Login(parent) {
    let loginInputEl = document.createElement('input');
    loginInputEl.type = 'text';
    parent.append(loginInputEl);
    loginInputEl.addEventListener('input', (event) => {
      if (this.onChange) {
        this.onChange();
      }
    });
    this.setValue = (value) => {
      loginInputEl.value = value;
    }
    this.getValue = () => {
      return loginInputEl.value;
    }
  }
  function Password(parent, open) {
    let passInputEl = document.createElement('input');
    parent.append(passInputEl);
    let passVisibilityCheckboxEl = document.createElement('input');
    passVisibilityCheckboxEl.type = 'checkbox';
    passVisibilityCheckboxEl.checked = open;
    parent.append(passVisibilityCheckboxEl);
    if (open) {
      passInputEl.type = 'text';
    } else {
      passInputEl.type = 'password';
    }
    passVisibilityCheckboxEl.addEventListener('change', (event) => {
      if (event.currentTarget.checked) {
        passInputEl.type = 'text';
      } else {
        passInputEl.type = 'password';
      }
      this.onOpenChange(event.currentTarget.checked);
    });
    passInputEl.addEventListener('input', (event) => {
      if (this.onChange) {
        this.onChange();
      }

    });
    this.setValue = (value) => {
      passInputEl.value = value;
    }
    this.getValue = () => {
      return passInputEl.value;
    }
    this.setOpen = (value) => {
      passVisibilityCheckboxEl.checked = value;
    }
    this.getOpen = () => {
      return passVisibilityCheckboxEl.checked;
    }
  }

  function loginPromise(parent) {
    function executor(resolve, reject) {
      const form = new LoginForm(parent);
      form.onSubmitForm = () => resolve({
        login: form.getLoginValue(),
        password: form.getPasswordValue(),
      });
    }

    return new Promise(executor);
  }


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