'use strict'

const Transform = require('stream').Transform
const lib = require('./lib')

/**
 * Create a Transform stream which will maintain a buffer with data received from a Readable
 * stream and push data to a Writable stream when the buffer can be matched againts the regex.
 * Will push the whole match object (or objects when the g flag is used) returned by
 * /regex/.exec(buffer).
 * @param {RegExp} regex Regular expression to execute
 * @return {Transform} A transform stream.
 */
function createRegexTransformStream(regex) {
    let buffer = ''

    const ts = new Transform({ objectMode: true })

    ts._transform = (chunk, _, next) => {
        let lastMatch
        let match
        buffer += chunk.toString()

        // thx stream-snitch
        // https://github.com/dmotz/stream-snitch/blob/master/index.js#L52
        // eslint-disable-next-line no-cond-assign
        while (match = regex.exec(buffer)) {
            ts.push(match)
            lastMatch = match
            if (!regex.global) break
        }
        if (lastMatch) {
            buffer = buffer.slice(lastMatch.index + lastMatch[0].length)
        }
        next()
    }

    return ts
}

/**
 * Create a replacement stream, which will push data when it's done replacing each incoming chunk.
 * @param {object|object[]} regex An object or array of objects
 * @param {RegExp} regex.re regular expression to match against
 * @param {string} regex.replacement a replacement string
 * @returns {Reabable} A readable stream.
 */
function replaceStream(regex) {
    const regexes = Array.isArray(regex) ? regex : [regex]
    const filteredRegexes = regexes.filter(lib.checkRegexObject)

    const ts = new Transform({ objectMode: false })

    ts._transform = (chunk, encoding, next) => {
        let string = String(chunk)
        filteredRegexes.forEach((reObject) => {
            string = string.replace(reObject.re, reObject.replacement)
        })
        ts.push(string)
        next()
    }

    return ts
}

Object.defineProperty(createRegexTransformStream, 'replaceStream', {
    get: () => replaceStream,
})

module.exports = createRegexTransformStream
