#!/usr/bin/env qore
# -*- mode: qore; indent-tabs-mode: nil -*-

%new-style
%enable-all-warnings
%require-types
%strict-args

%requires ../../../../qlib/Util.qm
%requires ../../../../qlib/Mime.qm
%requires ../../../../qlib/Logger.qm
%requires ../../../../qlib/HttpServerUtil.qm
%requires ../../../../qlib/HttpServer.qm
%requires ../../../../qlib/WebUtil.qm
%requires ../../../../qlib/QUnit.qm

%exec-class WebUtilTest

class TestFileHandler inherits FileHandler {
    public {
        bool addHeaders = False;
    }

    constructor(string fileRoot, string urlRoot = "/", *hash opt) : FileHandler(fileRoot, urlRoot, opt) {
    }

    private *hash<auto> getResponseHeadersForFile(string path, hash<auto> cx, hash<auto> hdr) {
        if (addHeaders)
            return {"Cache-Control": "private, max-age=86400"};
    }
}

public class WebUtilTest inherits QUnit::Test {
    public {
    }

    constructor() : Test("WebUtilTest", "1.0") {
        addTestCase("StaticTemplateManager test", \staticTemplateManagerTest());
        addTestCase("FileHandler test", \fileHandlerTest());
        addTestCase("StaticTemplateManager parse options test", \staticTemplateManagerParseOptionsTest());
        set_return_value(main());
    }

    staticTemplateManagerTest() {
        StaticTemplateManager stm();
        stm.add("t1", "<p>text</p>");
        stm.add("t2", "<p>text</p>");
    }

    private staticTemplateManagerParseOptionsTest() {
        # negative test
        try {
            StaticTemplateManager stm();
            stm.add("t1", "{% string s = 'foo bar'; %} {{ s }}");
            fail("test cannot go here");
        } catch (hash<ExceptionInfo> ex) {
            assertEq("TEMPLATE-ERROR", ex.err, "oldstyle PO with newstyle template");
            assertRegex("local variable 's' declared without '\\$' prefix, but parse option 'allow-bare-refs' is not set",
                     ex.desc, "oldstyle PO with newstyle template");
        }
        # positive test
        {
            StaticTemplateManager stm(PO_NEW_STYLE);
            stm.add("t1", "{% string s = 'foo bar'; %} {{ s }}");
            assertTrue(True);
        }
    }

    fileHandlerTest() {
        TestFileHandler fh(get_script_dir());

        Logger logger("test", LoggerLevel::getLevelInfo());
        if (m_options.verbose > 2) {
            logger.addAppender(new StdoutAppender());
        }
        hash<HttpServerOptionInfo> http_opts = <HttpServerOptionInfo>{
            "logger": logger,
            "debug": True,
        };
        HttpServer server(http_opts);
        server.setHandler("fh", "/", MimeTypeHtml, fh);
        server.setDefaultHandler("fh", fh);
        int port = server.addListener(<HttpListenerOptionInfo>{"service": 0}).port;

        on_exit delete server;

        HTTPClient client = new HTTPClient(("url": "http://localhost:" + port));
        client.connect();
        on_exit client.disconnect();

        hash<auto> info;
        auto result = client.get("/test_file.txt", NOTHING, \info);
        *hash<auto> respHdr = info."response-headers";
        assertEq("abc", trim(result));
        assertFalse(respHdr.hasKey("Cache-Control") || respHdr.hasKey("cache-control"));

        fh.addHeaders = True;
        result = client.get("/test_file.txt", NOTHING, \info);
        respHdr = info."response-headers";
        assertEq("abc", trim(result));
        # remove the "charset" from the content-type
        respHdr."content-type" =~ s/;.*//;
        assertEq(MimeTypeHtml, respHdr."content-type");
        assertTrue(respHdr.hasKey("Cache-Control") || respHdr.hasKey("cache-control"));
    }
}
