// ДЗ: Способы общения с серверами.  REST, GraphQL и JWT.
// задание 1 Светофор
{
  const delay = (ms) => new Promise((ok) => setTimeout(() => ok(ms), ms));

  async function trafficLight() {
    const greenLight = document.getElementById('green');
    const yellowLight = document.getElementById('yellow');
    const redLight = document.getElementById('red');

    while (true) {
      // включаем зеленый
      greenLight.style.backgroundColor = 'green';
      await delay(время_зеленого);

      // включаем желтый
      greenLight.style.backgroundColor = 'gray';
      yellowLight.style.backgroundColor = 'yellow';
      await delay(время_желтого);

      // включаем красный
      yellowLight.style.backgroundColor = 'gray';
      redLight.style.backgroundColor = 'red';
      await delay(время_красного);

      // выключаем красный
      redLight.style.backgroundColor = 'gray';
    }
  }
}

{
  // Stage 2
  const delay = (ms) => new Promise((ok) => setTimeout(() => ok(ms), ms));

  async function trafficLight(greenLight, yellowLight, redLight, greenTime, yellowTime, redTime) {
    while (true) {
      // включаем зеленый
      greenLight.style.backgroundColor = 'green';
      await delay(greenTime);

      // включаем желтый
      greenLight.style.backgroundColor = 'gray';
      yellowLight.style.backgroundColor = 'yellow';
      await delay(yellowTime);

      // включаем красный
      yellowLight.style.backgroundColor = 'gray';
      redLight.style.backgroundColor = 'red';
      await delay(redTime);

      // выключаем красный
      redLight.style.backgroundColor = 'gray';
    }
  }

  // использование функции
  const greenLight = document.getElementById('green');
  const yellowLight = document.getElementById('yellow');
  const redLight = document.getElementById('red');
  trafficLight(greenLight, yellowLight, redLight, 2000, 1000, 3000);
}

// задание 2 PedestrianTrafficLight
{
  const delay = (ms) => new Promise((ok) => setTimeout(() => ok(ms), ms));

  async function pedestrianLight(greenLight, redLight, greenTime, redTime) {
    while (true) {
      // включаем зеленый
      greenLight.style.backgroundColor = 'green';
      await delay(greenTime);

      // включаем красный
      greenLight.style.backgroundColor = 'gray';
      redLight.style.backgroundColor = 'red';
      await delay(redTime);
    }
  }

  // использование функции
  const greenLight = document.getElementById('green');
  const redLight = document.getElementById('red');
  pedestrianLight(greenLight, redLight, 5000, 2000);
}

{
  // Stage 2
  const delay = (ms) => new Promise((ok) => setTimeout(() => ok(ms), ms));

  function domEventPromise(element, event) {
    return new Promise((resolve) => {
      element.addEventListener(event, resolve, { once: true });
    });
  }

  async function pedestrianLight(greenLight, redLight, button, greenTime, redTime) {
    while (true) {
      // включаем зеленый
      greenLight.style.backgroundColor = 'green';
      redLight.style.backgroundColor = 'gray';

      // ожидаем событие кнопки или истечение времени
      await Promise.race([domEventPromise(button, 'click'), delay(greenTime)]);

      // включаем красный
      greenLight.style.backgroundColor = 'gray';
      redLight.style.backgroundColor = 'red';

      // ожидаем событие кнопки или истечение времени
      await Promise.race([domEventPromise(button, 'click'), delay(redTime)]);
    }
  }

  // использование функции
  const greenLight = document.getElementById('green');
  const redLight = document.getElementById('red');
  const button = document.getElementById('button');
  pedestrianLight(greenLight, redLight, button, 5000, 2000);
}
{
  // Stage 3
  const delay = (ms) => new Promise((ok) => setTimeout(() => ok(ms), ms));

  function domEventPromise(element, event) {
    return new Promise((resolve) => {
      element.addEventListener(event, resolve, { once: true });
    });
  }

  async function pedestrianLight(greenLight, redLight, button, greenTime, redTime, buttonDelay) {
    while (true) {
      // включаем зеленый
      greenLight.style.backgroundColor = 'green';
      redLight.style.backgroundColor = 'gray';
      // ожидаем событие кнопки, истечение времени или задержку кнопки
      await Promise.race([
        domEventPromise(button, 'click').then(() => delay(buttonDelay)),
        delay(greenTime),
      ]);

      // включаем красный
      greenLight.style.backgroundColor = 'gray';
      redLight.style.backgroundColor = 'red';

      // ожидаем событие кнопки, истечение времени или задержку кнопки
      await Promise.race([
        domEventPromise(button, 'click').then(() => delay(buttonDelay)),
        delay(redTime),
      ]);
    }
  }
}
// задание 3 speedtest
{
  async function speedtest(getPromise, count, parallel = 1) {
    let startTime = Date.now();
    let parallelDuration = 0;
    let queryDuration = 0;

    for (let i = 0; i < count; i++) {
      const promises = [];
      for (let j = 0; j < parallel; j++) {
        promises.push(getPromise());
      }

      const startParallelTime = Date.now();
      await Promise.all(promises);
      parallelDuration += Date.now() - startParallelTime;
      queryDuration += parallelDuration / parallel;
    }

    const duration = Date.now() - startTime;
    return {
      duration,
      querySpeed: queryDuration / count / 1000,
      queryDuration: queryDuration / count,
      parallelSpeed: parallelDuration / duration / 1000,
      parallelDuration: parallelDuration / count,
    };
  }

  // использование функции
  speedtest(() => delay(1000), 10, 10).then((result) => console.log(result));
  speedtest(() => fetch('http://swapi.dev/api/people/1').then((res) => res.json()), 10, 5).then(
    (result) => console.log(result),
  );
}

// задание 4 gql
{
  async function gql(endpoint, query, variables) {
    try {
      const response = await fetch(endpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Accept: 'application/json',
        },
        body: JSON.stringify({
          query,
          variables,
        }),
      });
      return response.json();
    } catch (error) {
      console.error(error);
      return null;
    }
  }

  // использование функции
  (async () => {
    const catQuery = `query cats($q: String){
          CategoryFind(query: $q){
          _id name
          }
          }`;
    const cats = await gql('http://shop-roles.node.ed.asmer.org.ua/graphql', catQuery, {
      q: '[{}]',
    });
    console.log(cats); // список категорий с _id name и всем таким прочим

    const loginQuery = `query login($login:String, $password:String){
            login(login:$login, password:$password)
             }`;
    const token = await gql('http://shop-roles.node.ed.asmer.org.ua/graphql', loginQuery, {
      login: 'test457',
      password: '123123',
    });
    console.log(token);
  })();
}

// задание 5 jwtDecode
{
  function jwtDecode(token) {
    if (!token) return;

    const [header, payload, signature] = token.split('.');
    if (!header || !payload || !signature) return;

    try {
      const decodedPayload = atob(payload);
      const data = JSON.parse(decodedPayload);
      return data;
    } catch {
      return;
    }
  }
}

{
  // использование:
  const token =
    'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOnsiaWQiOiI2MzIyMDVhZWI3NGUxZjVmMmVjMWEzMjAiLCJsb2dpbiI6InRlc3Q0NTciLCJhY2wiOlsiNjMyMjA1YWViNzRlMWY1ZjJlYzFhMzIwIiwidXNlciJdfSwiaWF0IjoxNjY4MjcyMTYzfQ.rxV1ki9G6LjT2IPWcqkMeTi_1K9sb3Si8vLB6UDAGdw';
  console.log(jwtDecode(token));

  // {
  //   "sub": {
  //     "id": "632205aeb74e1f5f2ec1a320",
  //     "login": "test457",
  //     "acl": [
  //       "632205aeb74e1f5f2ec1a320",
  //       "user"
  //     ]
  //   },
  //   "iat": 1668272163
  // }
  try {
    console.log(jwtDecode()); // undefined
    console.log(jwtDecode('дичь')); // undefined
    console.log(jwtDecode('ey.ey.ey')); //undefined

    console.log('до сюда доработало, а значит jwtDecode не матерился в консоль красным цветом');
  } finally {
    console.log('ДЗ, видимо, окончено');
  }
}
