/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
import { suite, test } from 'node:test';
import assert from 'node:assert/strict';
import * as embeddedSupport from '../modes/embeddedSupport.js';
import { getLanguageService } from 'vscode-html-languageservice';
import { TextDocument } from '../modes/languageModes.js';
suite('HTML Embedded Support', () => {
    const htmlLanguageService = getLanguageService();
    function assertLanguageId(value, expectedLanguageId) {
        const offset = value.indexOf('|');
        value = value.substr(0, offset) + value.substr(offset + 1);
        const document = TextDocument.create('test://test/test.html', 'html', 0, value);
        const position = document.positionAt(offset);
        const docRegions = embeddedSupport.getDocumentRegions(htmlLanguageService, document);
        const languageId = docRegions.getLanguageAtPosition(position);
        assert.strictEqual(languageId, expectedLanguageId);
    }
    function assertEmbeddedLanguageContent(value, languageId, expectedContent) {
        const document = TextDocument.create('test://test/test.html', 'html', 0, value);
        const docRegions = embeddedSupport.getDocumentRegions(htmlLanguageService, document);
        const content = docRegions.getEmbeddedDocument(languageId);
        assert.strictEqual(content.getText(), expectedContent);
    }
    function assertEmbeddedLanguageContents(value, languageId, expectedContents) {
        const document = TextDocument.create('test://test/test.html', 'html', 0, value);
        const docRegions = embeddedSupport.getDocumentRegions(htmlLanguageService, document);
        const contents = docRegions.getEmbeddedDocuments(languageId).map(content => content.getText());
        assert.deepStrictEqual(contents, expectedContents);
    }
    test('Styles', function () {
        assertLanguageId('|<html><style>foo { }</style></html>', 'html');
        assertLanguageId('<html|><style>foo { }</style></html>', 'html');
        assertLanguageId('<html><st|yle>foo { }</style></html>', 'html');
        assertLanguageId('<html><style>|foo { }</style></html>', 'css');
        assertLanguageId('<html><style>foo| { }</style></html>', 'css');
        assertLanguageId('<html><style>foo { }|</style></html>', 'css');
        assertLanguageId('<html><style>foo { }</sty|le></html>', 'html');
    });
    test('Styles - Incomplete HTML', function () {
        assertLanguageId('|<html><style>foo { }', 'html');
        assertLanguageId('<html><style>fo|o { }', 'css');
        assertLanguageId('<html><style>foo { }|', 'css');
    });
    test('Style in attribute', function () {
        assertLanguageId('<div id="xy" |style="color: red"/>', 'html');
        assertLanguageId('<div id="xy" styl|e="color: red"/>', 'html');
        assertLanguageId('<div id="xy" style=|"color: red"/>', 'html');
        assertLanguageId('<div id="xy" style="|color: red"/>', 'css');
        assertLanguageId('<div id="xy" style="color|: red"/>', 'css');
        assertLanguageId('<div id="xy" style="color: red|"/>', 'css');
        assertLanguageId('<div id="xy" style="color: red"|/>', 'html');
        assertLanguageId('<div id="xy" style=\'color: r|ed\'/>', 'css');
        assertLanguageId('<div id="xy" style|=color:red/>', 'html');
        assertLanguageId('<div id="xy" style=|color:red/>', 'css');
        assertLanguageId('<div id="xy" style=color:r|ed/>', 'css');
        assertLanguageId('<div id="xy" style=color:red|/>', 'css');
        assertLanguageId('<div id="xy" style=color:red/|>', 'html');
    });
    test('Style content', function () {
        assertEmbeddedLanguageContent('<html><style>foo { }</style></html>', 'css', '             foo { }               ');
        assertEmbeddedLanguageContent('<html><script>var i = 0;</script></html>', 'css', '                                        ');
        assertEmbeddedLanguageContent('<html><style>foo { }</style>Hello<style>foo { }</style></html>', 'css', '             foo { }                    foo { }               ');
        assertEmbeddedLanguageContent('<html>\n  <style>\n    foo { }  \n  </style>\n</html>\n', 'css', '\n         \n    foo { }  \n  \n\n');
        assertEmbeddedLanguageContent('<div style="color: red"></div>', 'css', '         __{color: red}       ');
        assertEmbeddedLanguageContent('<div style=color:red></div>', 'css', '        __{color:red}      ');
    });
    test('Scripts', function () {
        assertLanguageId('|<html><script>var i = 0;</script></html>', 'html');
        assertLanguageId('<html|><script>var i = 0;</script></html>', 'html');
        assertLanguageId('<html><scr|ipt>var i = 0;</script></html>', 'html');
        assertLanguageId('<html><script>|var i = 0;</script></html>', 'javascript');
        assertLanguageId('<html><script>var| i = 0;</script></html>', 'javascript');
        assertLanguageId('<html><script>var i = 0;|</script></html>', 'javascript');
        assertLanguageId('<html><script>var i = 0;</scr|ipt></html>', 'html');
        assertLanguageId('<script type="text/javascript">var| i = 0;</script>', 'javascript');
        assertLanguageId('<script type="text/ecmascript">var| i = 0;</script>', 'javascript');
        assertLanguageId('<script type="application/javascript">var| i = 0;</script>', 'javascript');
        assertLanguageId('<script type="application/ecmascript">var| i = 0;</script>', 'javascript');
        assertLanguageId('<script type="application/typescript">var| i = 0;</script>', undefined);
        assertLanguageId('<script type=\'text/javascript\'>var| i = 0;</script>', 'javascript');
    });
    test('Scripts in attribute', function () {
        assertLanguageId('<div |onKeyUp="foo()" onkeydown=\'bar()\'/>', 'html');
        assertLanguageId('<div onKeyUp=|"foo()" onkeydown=\'bar()\'/>', 'html');
        assertLanguageId('<div onKeyUp="|foo()" onkeydown=\'bar()\'/>', 'javascript');
        assertLanguageId('<div onKeyUp="foo(|)" onkeydown=\'bar()\'/>', 'javascript');
        assertLanguageId('<div onKeyUp="foo()|" onkeydown=\'bar()\'/>', 'javascript');
        assertLanguageId('<div onKeyUp="foo()"| onkeydown=\'bar()\'/>', 'html');
        assertLanguageId('<div onKeyUp="foo()" onkeydown=|\'bar()\'/>', 'html');
        assertLanguageId('<div onKeyUp="foo()" onkeydown=\'|bar()\'/>', 'javascript');
        assertLanguageId('<div onKeyUp="foo()" onkeydown=\'bar()|\'/>', 'javascript');
        assertLanguageId('<div onKeyUp="foo()" onkeydown=\'bar()\'|/>', 'html');
        assertLanguageId('<DIV ONKEYUP|=foo()</DIV>', 'html');
        assertLanguageId('<DIV ONKEYUP=|foo()</DIV>', 'javascript');
        assertLanguageId('<DIV ONKEYUP=f|oo()</DIV>', 'javascript');
        assertLanguageId('<DIV ONKEYUP=foo(|)</DIV>', 'javascript');
        assertLanguageId('<DIV ONKEYUP=foo()|</DIV>', 'javascript');
        assertLanguageId('<DIV ONKEYUP=foo()<|/DIV>', 'html');
        assertLanguageId('<label data-content="|Checkbox"/>', 'html');
        assertLanguageId('<label on="|Checkbox"/>', 'html');
    });
    test('Script content', function () {
        assertEmbeddedLanguageContent('<html><script>var i = 0;</script></html>', 'javascript', '              var i = 0;                ');
        assertEmbeddedLanguageContent('<script type="text/javascript">var i = 0;</script>', 'javascript', '                               var i = 0;         ');
        assertEmbeddedLanguageContent('<script><!--this comment should not give error--></script>', 'javascript', '        /* this comment should not give error */         ');
        assertEmbeddedLanguageContent('<script><!--this comment should not give error--> console.log("logging");</script>', 'javascript', '        /* this comment should not give error */ console.log("logging");         ');
        assertEmbeddedLanguageContent('<script>var data=100; <!--this comment should not give error--> </script>', 'javascript', '        var data=100; /* this comment should not give error */          ');
        assertEmbeddedLanguageContent('<script>/* --> */</script>', 'javascript', '        /* --> */         ');
        assertEmbeddedLanguageContent('<script>/* --> ----------------------------- */</script>', 'javascript', '        /* --> ----------------------------- */         ');
        assertEmbeddedLanguageContent('<script><!--commnet1-->\n<!--conment2--></script>', 'javascript', '        /* commnet1 */\n/* conment2 */         ');
        assertEmbeddedLanguageContent('<script><!--a--> foo(); <!--b--></script>', 'javascript', '        /* a */ foo(); /* b */         ');
        assertEmbeddedLanguageContent('<div onKeyUp="foo()" onkeydown="bar()"/>', 'javascript', '              foo();            bar();  ');
        assertEmbeddedLanguageContent('<div onKeyUp="return"/>', 'javascript', '              return;  ');
        assertEmbeddedLanguageContent('<div onKeyUp=return\n/><script>foo();</script>', 'javascript', '             return;\n          foo();         ');
    });
    test('Scripts with type module', function () {
        assertLanguageId('<script type="module">var| i = 0;</script>', 'javascript');
        assertLanguageId('<script type=module>var| i = 0;</script>', 'javascript');
        assertLanguageId('<script type="Module">var| i = 0;</script>', 'javascript');
        assertLanguageId('<script type=MODULE>var| i = 0;</script>', 'javascript');
    });
    test('Script content - module validation documents', function () {
        assertEmbeddedLanguageContent('<script>let a = 1;</script><script type="module">let a = 2;</script>', 'javascript', '        let a = 1;                               let a = 2;         ');
        assertEmbeddedLanguageContents('<script>let a = 1;</script><script type="module">let a = 2;</script>', 'javascript', [
            '        let a = 1;                                                  ',
            '                                                 let a = 2;         \nexport {};'
        ]);
    });
    test('Script content - HTML escape characters', function () {
        assertEmbeddedLanguageContent('<div style="font-family: &quot;Arial&quot;"></div>', 'css', '         __{font-family: "     Arial     "}       ');
        assertEmbeddedLanguageContent('<div style="font-family: &#34;Arial&#34;"></div>', 'css', '         __{font-family: "    Arial    "}       ');
        assertEmbeddedLanguageContent('<div style="font-family: &quot;Arial&#34;"></div>', 'css', '         __{font-family: "     Arial    "}       ');
        assertEmbeddedLanguageContent('<div style="font-family:&quot; Arial &quot; "></div>', 'css', '         __{font-family:     " Arial      " }       ');
        assertEmbeddedLanguageContent('<div style="font-family: Arial"></div>', 'css', '         __{font-family: Arial}       ');
    });
});
