//Async/Await Homework 2
//Светофор
let traficLightsForCars       = document.querySelectorAll(".traffic-lights__light--for-cars");
let traficLightsForPedestrian = document.querySelectorAll(".traffic-lights__light--for-pedestrian");
let button                    = document.querySelector(".traffic-lights__pedestrian-button");

let delay = async function(ms) {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(ms), ms);
    });
};

let domEventPromise = function(el, eventName) {
  return new Promise((resolve, reject) => {
      let resolveEl = function() {
          resolve(el);

          el.removeEventListener(eventName, resolveEl)
      };

      el.addEventListener(eventName, resolveEl);
  });
};

let toggleTraficLights = function(el, indexLightRemove, indexLightAdd, lightRemove, lightAdd) { // Функция которая отвечает за переключения цветов у светофора
    el[indexLightRemove].classList.remove(`traffic-lights__light--${lightRemove}`);
    el[indexLightAdd].classList.add(`traffic-lights__light--${lightAdd}`);
};

let countWorkingLightTime = async function(ms, indexCounter) { // Супер некрасивая, костыльная функция которая отвечает за обратный отсчет времени работы конкретного цвета у светофора
    const TIME = ms / 1000;

    let span = document.createElement("span");                 // Создаю и стилизирую span в котором в дальнейшем буду вести обратный отсчет
        span.classList.add("traffic-lights__counter");

    for(let i = 0; i < traficLightsForCars.length; i++) {                                       // Собсна сам костыль, ранее, при досрочном переключении светофора с зеленого на красный, функция countWorkingLightTime все равно продолжала вести обратный отсчет
        if(traficLightsForCars[i].firstElementChild) {                                          // Теперь, с добавлением этой логики, при следующем (досрочном) вызове countWorkingLightTime, он сначала удаляет все спаны в которых ведутся обратные отсчеты
            traficLightsForCars[i].removeChild(traficLightsForCars[i].firstElementChild);       // Предыдущая функция countWorkingLightTime которая отрисовывала счетчик у зеленого светофора больше не работает, т.к.
        };
    };

    traficLightsForCars[indexCounter].appendChild(span);  // Помещаю спан в котором буду вести отсчет в активный светофор

    for(let i = TIME; i > 0; i--) {
        traficLightsForCars[indexCounter].querySelector(".traffic-lights__counter").textContent = i;

        await delay(1000);
    };

    traficLightsForCars[indexCounter].querySelector(".traffic-lights__counter").textContent = "";
};

let runTrafficLight = async function() {
    const FIRST_TRAFIC_LIGHT_FOR_CAR = 0;
    const SECOND_TRAFIC_LIGHT_FOR_CAR = 1;
    const THIRD_TRAFIC_LIGHT_FOR_CAR = 2;

    const FIRST_TRAFIC_LIGHT_FOR_PEDESTRING = 0;
    const SECOND_TRAFIC_LIGHT_FOR_PEDESTRING = 1;

    const WORKING_TIME_RED = 10000;
    const WORKING_TIME_YELLOW = 5000;
    const WORKING_TIME_GREEN = 15000;

    while(true) {
              toggleTraficLights(traficLightsForCars, THIRD_TRAFIC_LIGHT_FOR_CAR, FIRST_TRAFIC_LIGHT_FOR_CAR, "green", "red");
              toggleTraficLights(traficLightsForPedestrian, FIRST_TRAFIC_LIGHT_FOR_PEDESTRING, 1, "red", "green");
        await countWorkingLightTime(WORKING_TIME_RED, FIRST_TRAFIC_LIGHT_FOR_CAR);
              
              toggleTraficLights(traficLightsForCars, FIRST_TRAFIC_LIGHT_FOR_CAR, SECOND_TRAFIC_LIGHT_FOR_CAR, "red", "yellow");
        await countWorkingLightTime(WORKING_TIME_YELLOW, SECOND_TRAFIC_LIGHT_FOR_CAR);

              toggleTraficLights(traficLightsForCars, SECOND_TRAFIC_LIGHT_FOR_CAR, THIRD_TRAFIC_LIGHT_FOR_CAR, "yellow", "green");
              toggleTraficLights(traficLightsForPedestrian, SECOND_TRAFIC_LIGHT_FOR_PEDESTRING, FIRST_TRAFIC_LIGHT_FOR_PEDESTRING, "green", "red");
        await Promise.race([countWorkingLightTime(WORKING_TIME_GREEN, THIRD_TRAFIC_LIGHT_FOR_CAR), domEventPromise(button, "click")]);
    };
};

runTrafficLight();


//speedtest
let speedtest = async function(getPromise, count, parallel = 1) {
    const SPEEDTEST_START = new Date().getTime();

    let parallelStartArr = []; // Массивы в которых я буду хранить таймспан времени начала и конца работы одного Promise.all
    let parallelEndArr = [];   // Для дальнейших вычислений средней времени работы

    let pushPromiseInArr = function() {
        let arrForParallelQueries = [];

        for(let i = 0; i < parallel; i++) {
            arrForParallelQueries.push(getPromise());
        };

        return arrForParallelQueries;
    };

    let countMeanParallelWork = function(startArr, endArr) {
        let meanStart = 0;
        let meanEnd = 0;

        for(let timespan of startArr) {
            meanStart += timespan;
        };

        for(let timespan of endArr) {
            meanEnd += timespan;
        };

        return (meanEnd - meanStart) / startArr.length;
    };

    for(let i = 0; i < count; i++) {
        parallelStartArr.push(new Date().getTime());
        await Promise.all(pushPromiseInArr());
        parallelEndArr.push(new Date().getTime());
    };

    const SPEEDTEST__END = new Date().getTime();

    let duration         = SPEEDTEST__END - SPEEDTEST_START;
    let querySpeed       = duration / 1000;
    let queryDuration    = countMeanParallelWork(parallelStartArr, parallelEndArr);
    let parallelSpeed    = countMeanParallelWork(parallelStartArr, parallelEndArr) / (count * parallel);
    let parallelDuration = count * parallel;

    return {
        duration,
        querySpeed,
        queryDuration,
        parallelSpeed,
        parallelDuration
    };
};