'use strict';
const singleComment = Symbol('singleComment');
const multiComment = Symbol('multiComment');
const stripWithoutWhitespace = () => '';
const stripWithWhitespace = (string, start, end) => string.slice(start, end).replace(/\S/g, ' ');

const isEscaped = (jsonString, quotePosition) => {
    let index = quotePosition - 1;
    let backslashCount = 0;

    while (jsonString[index] === '\\') {
        index -= 1;
        backslashCount += 1;
    }

    return Boolean(backslashCount % 2);
};

module.exports = (jsonString, options = {}) => {
    if (typeof jsonString !== 'string') {
        throw new TypeError(`Expected argument \`jsonString\` to be a \`string\`, got \`${typeof jsonString}\``);
    }

    const strip = options.whitespace === false ? stripWithoutWhitespace : stripWithWhitespace;

    let insideString = false;
    let insideComment = false;
    let offset = 0;
    let result = '';

    for (let i = 0; i < jsonString.length; i++) {
        const currentCharacter = jsonString[i];
        const nextCharacter = jsonString[i + 1];

        if (!insideComment && currentCharacter === '"') {
            const escaped = isEscaped(jsonString, i);
            if (!escaped) {
                insideString = !insideString;
            }
        }

        if (insideString) {
            continue;
        }

        if (!insideComment && currentCharacter + nextCharacter === '//') {
            result += jsonString.slice(offset, i);
            offset = i;
            insideComment = singleComment;
            i++;
        } else if (insideComment === singleComment && currentCharacter + nextCharacter === '\r\n') {
            i++;
            insideComment = false;
            result += strip(jsonString, offset, i);
            offset = i;
            continue;
        } else if (insideComment === singleComment && currentCharacter === '\n') {
            insideComment = false;
            result += strip(jsonString, offset, i);
            offset = i;
        } else if (!insideComment && currentCharacter + nextCharacter === '/*') {
            result += jsonString.slice(offset, i);
            offset = i;
            insideComment = multiComment;
            i++;
            continue;
        } else if (insideComment === multiComment && currentCharacter + nextCharacter === '*/') {
            i++;
            insideComment = false;
            result += strip(jsonString, offset, i + 1);
            offset = i + 1;
            continue;
        }
    }

    return result + (insideComment ? strip(jsonString.slice(offset)) : jsonString.slice(offset));
};