function getRandomNumberAsync (max, callbackFn) {
    var runFor = 1000 + Math.random() * 1000;
    setTimeout(function() {
        var result = Math.random() * max;
        callbackFn(result);
    }, runFor);
}

getRandomNumberAsync(10, function(number) {
    console.log(number); // zwraca liczbę z zakresu od 0 do 10
});



function getRandomNumberWS (max, callbackFn) {
    $.getJSON('https://qrng.anu.edu.au/API/jsonI.php?length=1&type=uint16', function(json) {
        var result = json.data[0] / 65535 * max;
        callbackFn(result);
    });
}

getRandomNumberWS(10, function(number) {
    console.log(number);
});


function getRandomNumberWS (max, callbackFn, errorFn) {
    $.getJSON('https://qrng.anu.edu.au/API/jsonI.php?length=1&type=uint16', function(json) {
        var result = json.data[0] / 65535 * max;
        callbackFn(result);
    }).fail(errorFn);
}

getRandomNumberWS(10, function(number) {
    console.log(number);
}, function(error) {
    console.error(error);
});


function getRandomNumberWS (max, callbackFn, errorFn) {
    $.ajax({
        url: 'https://qrng.anu.edu.au/API/jsonI.php?length=1&type=uint16',
        dataType: 'json',
        success: function(json) {
            var result = json.data[0] / 65535 * max;
            callbackFn(result);
        },
        error: errorFn
    });
}

getRandomNumberWS(10, function(number) {
    console.log(number);
}, function(error) {
    console.error(error);
});


function getThreeRandomNumbers(callbackFn, errorFn) {
    var results = [];
    getRandomNumberAsync(10, function(number) {
        results.push(number);

        getRandomNumberAsync(10, function(number) {
            results.push(number);

            getRandomNumberWS(10, function(number) {
                results.push(number);
                callbackFn(results);
            }, function (error) {
                errorFn(error);
            });
        });
    });
}

getThreeRandomNumbers(function(number) {
    console.log(number);
}, function(error) {
    console.error(error);
});



function getThreeRandomNumbers(callbackFn, errorFn) {
    var results = [];

    // task 1
    getRandomNumberAsync(10, function(number) {
        results.push(number);
        task2();
    });

    function task2 () {
        getRandomNumberAsync(10, function(number) {
            results.push(number);
            task3();
        });
    }

    function task3 () {
        getRandomNumberWS(10, function(number) {
            results.push(number);
            callbackFn(results);
        }, errorFn);
    }
}

getThreeRandomNumbers(function(number) {
    console.log(number);
}, function(error) {
    console.error(error);
});



function getRandomNumbersSerial(n, callbackFn) {
    var results = [];

    function step() {
        getRandomNumberAsync(10, function(number) {
            results.push(number);
            if (results.length === n) {
                callbackFn(results);
                return;
            }
            step();
        });
    }
    step();
}

getRandomNumbersSerial(3, function(number) {
    console.log(number);
});



function getRandomNumbersConcurent(callbackFn, errorFn) {
    var results = [];
    var resultCount = 0;
    var n = 3;

    function gatherResult (resultPos) {
        return function (result) {
            results[resultPos] = result;
            resultCount++;
            if (resultCount === n) {
                callbackFn(results);
            }
        };
    }
    
    getRandomNumberAsync(10, gatherResult(0));
    getRandomNumberAsync(10, gatherResult(1));
    getRandomNumberWS(10, gatherResult(2), errorFn);
}

getRandomNumbersConcurent(function(number) {
    console.log(number);
}, function(error) {
    console.error(error);
});



function getRandomNumbersConcurent(callbackFn) {
    var results = [];
    var callCount = 0;
    var resultCount = 0;
    var n = 3;

    function gatherResult () {
        var resultPos = callCount++;
        return function (result) {
            results[resultPos] = result;
            resultCount++;
            if (resultCount === n) {
                callbackFn(results);
            }
        };
    }
    
    getRandomNumberAsync(10, gatherResult());
    getRandomNumberAsync(10, gatherResult());
    getRandomNumberWS(10, gatherResult());
}

getRandomNumbersConcurent(function(number) {
    console.log(number);
});



function getRandomNumbersConcurent(callbackFn) {
    var results = [];
    var callCount = 0;
    var resultCount = 0;

    function gatherResult () {
        var resultPos = callCount++;
        return function (result) {
            results[resultPos] = result;
            // Sprawdzenie, czy jest to wywołanie asynchroniczne
            setTimeout(function () {
                resultCount++;
                if (resultCount === callCount) {
                    callbackFn(results);
                }
            }, 0);
        };
    }
    
    getRandomNumberAsync(10, gatherResult());
    getRandomNumberAsync(10, gatherResult());
    getRandomNumberWS(10, gatherResult());
    getRandomNumberWS(10, gatherResult());
}

getRandomNumbersConcurent(function(number) {
    console.log(number);
});



// Wyniki nie są zgodne z kolejnością wywołań
function getRandomNumbersConcurent(callbackFn) {
    var results = [];
    var n = 3;

    function gatherResults (number) {
        results.push(number);
        if (results.length === n) {
            callbackFn(results);
        }
    }
    
    getRandomNumberAsync(10, gatherResults);
    getRandomNumberAsync(10, gatherResults);
    getRandomNumberWS(10, gatherResults);
}

getRandomNumbersConcurent(function(number) {
    console.log(number);
});



function getRandomNumbersConcurentFor(n, callbackFn) {
    var results = [];
    
    for (var i = 0; i < n; i++) {
        getRandomNumberAsync(10, function(number) {
            results.push(number);
            if (results.length === n) {
                callbackFn(results);
            }
        });
    }
}

getRandomNumbersConcurentFor(3, function(number) {
    console.log(number);
});
