// makeProfileTimer
function makeProfileTimer() {
    let old = performance.now()
    function remembered() {
        return performance.now() - old
    }
    return remembered
}
let timer = makeProfileTimer()
alert('hello')
alert(timer())

// makeSaver
function makeSaver(func) {
    let value = func
    return () => {
        function vault() {
            value =  value()
        }
        if(typeof value === 'function') vault()
        return value
    }
}

var saver = makeSaver(Math.random) //создает функцию-хранилище результата переданной в качестве параметра функции (Math.random 
// в примере). На этом этапе Math.random НЕ вызывается
var value1 = saver()              //saver вызывает переданную в makeSaver функцию, запоминает результат и возвращает его
var value2 = saver()              //saver в дальнейшем просто хранит результат функции, и более НЕ вызывает переданную 
//в makeSaver функцию;
console.log('is?', value1, value2)
console.log('is equal?', value1 === value2)                 // всегда true

var saver2 = makeSaver(() => console.log('saved function called') || [null, undefined, false, '', 0, Math.random()][Math.ceil(Math.random() * 6)])
var value3 = saver2()
var value4 = saver2()
console.log('3 & 4', value3, value4)
console.log('is equal?', value3 === value4) // тоже должно быть true

let namePrompt = prompt.bind(window, 'Как тебя зовут?')
let nameSaver = makeSaver(namePrompt)
alert(`Привет! Prompt еще не было!`)
alert(`Привет ${nameSaver()}. Только что запустился prompt, первый и последний раз`)
alert(`Слушай, ${nameSaver()}, го пить пиво. Ведь prompt был только один раз`)



// Final Countdown
var finalCountdown = (function (sec) {
    var counter = sec;
    return function repeat() {
        window.setTimeout(()=>{
            if(counter > 0) {
                console.log(counter)
                counter -= 1
                repeat()
            } else {
                return console.log('поехали')
            }
        },1000)
    }
})(5);
finalCountdown()

// myBind
let myBind = function myBind(func, context, [...args]) {
    return function inner(...used) {
        let arr = [...args]
        let j = 0
        for(let i = 0; i < arr.length; i++) {
            if(arr[i] === undefined) {
                arr[i] = [...used][j]
                j++
            }
        }
        return func.apply(context, arr)
    }
}

let pow5 = myBind(Math.pow, Math, [undefined, 5])
console.log(pow5(2))
console.log(pow5(3))
console.log(pow5(1))

console.log(Math.pow.apply(Math, [2,5]))

var chessMin = myBind(Math.min, Math, [undefined, 4, undefined, 5,undefined, 8,undefined, 9])
console.log(chessMin(-1,-5,3,15)) // вызывает Math.min(-1, 4, -5, 5, 3, 8, 15, 9), результат -5

var zeroPrompt = myBind(prompt, window, [undefined, "0"]) // аналогично, только теперь задается "0" как текст по умолчанию в prompt, 
                                                          // а текст приглашения пользователя задается при вызове zeroPrompt
                                                        //var someNumber = zeroPrompt("Введите число")
console.log(myBind((...params) => params.join(''), null, [undefined, 'b', undefined, undefined, 'e', 'f'])('a','c','d') === 'abcdef')