const fetch = require('node-fetch')
const retry = require('async-retry')

const parser = require('../utils/parser')

const defaultConfig = {
    retries: 5,
    factor: 3,
    minTimeout: 1000,
    maxTimeout: 60000,
    randomize: true
}

const validateSong = (song, action) => {
    const isValid = song && song.verses && song.verses.length
    if(!isValid && typeof action === 'function') {
        return action()
    }
    return song
}

class Scraper {
    constructor({ url, config = defaultConfig }) {
        this.url = url
        this.config = config
    }

    async fetchPreviews() {
        const response = await fetch(`${this.url}/texts`)
        const html = await response.textConverted()
        return parser.parsePreviews(html)
    }

    async fetchSongs() {
        const previews = await this.fetchPreviews()
        const songs = await Promise.all(previews.map(preview => this.fetchSong(preview.id)))
        return songs
    }

    async fetchSong(id) {
        return await retry(async () => {
            console.debug(`Fetching song with id - ${id} - ${new Date()}`)
            const response = await fetch(`${this.url}/text_print.php?area=go_texts&id=${id}`)
            const html = await response.textConverted()
            const song = parser.parseSong(html)
            return validateSong(song, () => {
                throw new Error('Invalid song')
            })
        }, this.config)
    }
}

module.exports = Scraper

@@ -251,195 +251,409 @@
 date
-Song = (song, action) =%3E %7B%0A    const isValid = song && song.verses && song.verses.length%0A    if(!isValid && typeof action === 'function') %7B%0A        return action()%0A    %7D%0A    return song%0A%7D
+Factory = (validationPredicate, errorSupplier) =%3E object =%3E %7B%0A    if(!validationPredicate(object)) %7B%0A        const error = typeof errorSupplier === 'function' ? errorSupplier() : new Error(%22Validation failed%22)%0A        throw error%0A    %7D%0A    return object%0A%7D%0A%0Aconst validateSong = validateFactory(%0A    song =%3E !!(song && song.verses && song.verses.length),%0A    () =%3E new Error('Song validation failed')%0A)
 %0A%0Acl
@@ -1541,79 +1541,8 @@
 song
-, () =%3E %7B%0A                throw new Error('Invalid song')%0A            %7D
 )%0A  

improve validation code