// test.js
import {expect} from "chai";
import {
    parseBracketedKeyValueHash,
    createBracketedKeyValueHash
} from "../../../source/text/bracketed-key-value-hash.mjs";

describe("parseBracketedKeyValueHash", () => {
    it("should return an empty object for an empty string", () => {
        const input = "";
        const expectedResult = {};
        expect(parseBracketedKeyValueHash(input)).to.deep.equal(expectedResult);
    });

    it("should parse a single selector with one key-value pair", () => {
        const input = "#selector1(key1=value1)";
        const expectedResult = {
            selector1: {
                key1: "value1",
            },
        };
        expect(parseBracketedKeyValueHash(input)).to.deep.equal(expectedResult);
    });

    it("should parse multiple selectors with multiple key-value pairs", () => {
        const input = "#selector1(key1=value1,key2=value2);selector2(key3=value3,key4=value4)";
        const expectedResult = {
            selector1: {
                key1: "value1",
                key2: "value2",
            },
            selector2: {
                key3: "value3",
                key4: "value4",
            },
        };
        expect(parseBracketedKeyValueHash(input)).to.deep.equal(expectedResult);
    });

    it("should decode URL-encoded values", () => {
        const input = "#selector1(key1=value1%2Cwith%20comma)";
        const expectedResult = {
            selector1: {
                key1: "value1,with comma",
            },
        };
        const result = parseBracketedKeyValueHash(input);
        expect(result.selector1.key1).to.equal(expectedResult.selector1.key1);
    });

    it("should handle input without a leading hash", () => {
        const input = "selector1(key1=value1)";
        const expectedResult = {
            selector1: {
                key1: "value1",
            },
        };
        expect(parseBracketedKeyValueHash(input)).to.deep.equal(expectedResult);
    });

    it("should return an empty object for invalid input", () => {
        const input = "#selector1(key1=value1,key2";
        const expectedResult = {};
        expect(parseBracketedKeyValueHash(input)).to.deep.equal(expectedResult);
    });

    it('should return an empty object for an empty input string', () => {
        const hashString = '';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({});
    });

    it('should return an empty object for an invalid input string', () => {
        const hashString = '#invalid';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({});
    });

    it('should parse a simple input string with one selector and one key-value pair', () => {
        const hashString = '#selector(key=value)';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({selector: {key: 'value'}});
    });

    it('should parse an input string with multiple selectors and key-value pairs', () => {
        const hashString = '#selector1(key1=value1);selector2(key2=value2)';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({selector1: {key1: 'value1'}, selector2: {key2: 'value2'}});
    });

    it('should handle empty values', () => {
        const hashString = '#selector(key1=,key2=)';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({selector: {key1: '', key2: ''}});
    });

    it('should handle percent-encoded values', () => {
        const hashString = '#selector(key1=value%201,key2=value%2C2)';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({selector: {key1: 'value 1', key2: 'value,2'}});
    });

    it('should handle double-quoted values with commas', () => {
        const hashString = '#selector(key1="value,1",key2="value,2")';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({selector: {key1: 'value,1', key2: 'value,2'}});
    });

    it('should ignore leading hash symbol (#)', () => {
        const hashString = 'selector(key=value)';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({selector: {key: 'value'}});
    });

    it('should ignore leading and trailing white space', () => {
        const hashString = '  #selector(key=value)  ';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({selector: {key: 'value'}});
    });

    it('should return an empty object if the input string ends prematurely', () => {
        const hashString = '#selector(key=value';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({});
    });

    it('should return an empty object if a selector is missing', () => {
        const hashString = '#(key=value)';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({});
    });

    it('should return an empty object if a key is missing', () => {
        const hashString = '#selector(=value)';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({});
    });

    it('should return an empty object ifa value is missing', () => {
        const hashString = '#selector(key=)';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({
            selector: {
                key: '',
            },
        });
    });

    it('should return an empty object if there is no closing parenthesis for a selector', () => {
        const hashString = '#selector(key=value;';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({});
    });

    it('should return an empty object if there is no semicolon after a selector', () => {
        const hashString = '#selector(key=value)selector2(key2=value2)';
        const result = parseBracketedKeyValueHash(hashString);
        expect(result).to.deep.equal({
            selector: {
                key: 'value',
            },
            selector2: {
                key2: 'value2',
            },
        });
    });

    describe('createBracketedKeyValueHash', () => {
        it('should return an hash string for a simple object', () => {
            const input = {
                '.example': {
                    'color': 'red',
                    'font-size': '14px'
                },
                '.other': {
                    'background': 'blue'
                }
            };

            const result = createBracketedKeyValueHash(input);
            expect(result).to.deep.equal("#.example(color=red,font-size=14px);.other(background=blue)");
        });
        
        it('should return a url-encoded hash string for a simple object', () => {
            const input = {
                '.example': {
                    'color': 'r"ed',
                    'font-size': '14px'
                },
                '.other': {
                    'background': 'blue'
                }
            };

            const result = createBracketedKeyValueHash(input, true);
            expect(result).to.deep.equal("#.example(color=r%22ed,font-size=14px);.other(background=blue)");
        });
        
        it('should return an empty string for an empty object', () => {
            const input = {};
            const result = createBracketedKeyValueHash(input,false);
            expect(result).to.deep.equal("");
        });
        
        it('should return an empty string for an empty object', () => {
            const input = {};
            const result = createBracketedKeyValueHash(input,false);
            expect(result).to.deep.equal("");
        });
        
    });


});
