// Lux Runtime
const Lux = {
    Some: (value) => ({ tag: "Some", value }),
    None: () => ({ tag: "None" }),
    
    Ok: (value) => ({ tag: "Ok", value }),
    Err: (error) => ({ tag: "Err", error }),
    
    Cons: (head, tail) => [head, ...tail],
    Nil: () => [],
    
    defaultHandlers: {
        Console: {
            print: (msg) => console.log(msg),
            readLine: () => {
                if (typeof require !== 'undefined') {
                    const readline = require('readline');
                    const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
                    return new Promise(resolve => rl.question('', answer => { rl.close(); resolve(answer); }));
                }
                return prompt('') || '';
            },
            readInt: () => parseInt(Lux.defaultHandlers.Console.readLine(), 10)
        },
        Random: {
            int: (min, max) => Math.floor(Math.random() * (max - min + 1)) + min,
            bool: () => Math.random() < 0.5,
            float: () => Math.random()
        },
        Time: {
            now: () => Date.now(),
            sleep: (ms) => new Promise(resolve => setTimeout(resolve, ms))
        },
        Http: {
            get: async (url) => {
                try {
                    const response = await fetch(url);
                    const body = await response.text();
                    const headers = [];
                    response.headers.forEach((v, k) => headers.push([k, v]));
                    return Lux.Ok({ status: response.status, body, headers });
                } catch (e) {
                    return Lux.Err(e.message);
                }
            },
            post: async (url, body) => {
                try {
                    const response = await fetch(url, { method: 'POST', body });
                    const respBody = await response.text();
                    const headers = [];
                    response.headers.forEach((v, k) => headers.push([k, v]));
                    return Lux.Ok({ status: response.status, body: respBody, headers });
                } catch (e) {
                    return Lux.Err(e.message);
                }
            },
            postJson: async (url, json) => {
                try {
                    const response = await fetch(url, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify(json)
                    });
                    const body = await response.text();
                    const headers = [];
                    response.headers.forEach((v, k) => headers.push([k, v]));
                    return Lux.Ok({ status: response.status, body, headers });
                } catch (e) {
                    return Lux.Err(e.message);
                }
            }
        }
    }
};

// Model constructors
function Counter_lux(field0) { return { tag: "Counter", field0: field0 }; }

// Msg constructors
const Increment_lux = { tag: "Increment" };
const Decrement_lux = { tag: "Decrement" };
const Reset_lux = { tag: "Reset" };

function getCount_lux(m) {
    const _match_0 = m;
    let _result_1;
    if (_match_0.tag === "Counter") {
        const n = _match_0.field0;
        _result_1 = n;
    } else {
        throw new Error('Non-exhaustive match on ' + JSON.stringify(_match_0));
    }
    return _result_1;
}

function init_lux() {
    return Counter_lux(0);
}

function update_lux(model, msg) {
    const _match_2 = msg;
    let _result_3;
    if (_match_2.tag === "Increment") {
        _result_3 = Counter_lux((getCount_lux(model) + 1));
    } else if (_match_2.tag === "Decrement") {
        _result_3 = Counter_lux((getCount_lux(model) - 1));
    } else if (_match_2.tag === "Reset") {
        _result_3 = Counter_lux(0);
    } else {
        throw new Error('Non-exhaustive match on ' + JSON.stringify(_match_2));
    }
    return _result_3;
}

function view_lux(model) {
    const count_4 = getCount_lux(model);
    return (((((((((("<div class=\"counter\">" + "<h1>Lux Counter</h1>") + "<div class=\"display\">") + String(count_4)) + "</div>") + "<div class=\"buttons\">") + "<button onclick=\"dispatch('Decrement')\">-</button>") + "<button onclick=\"dispatch('Reset')\">Reset</button>") + "<button onclick=\"dispatch('Increment')\">+</button>") + "</div>") + "</div>");
}

function luxInit_lux() {
    return init_lux();
}

function luxUpdate_lux(model, msgName) {
    const _match_5 = msgName;
    let _result_6;
    if (_match_5 === "Increment") {
        _result_6 = update_lux(model, Increment_lux);
    } else if (_match_5 === "Decrement") {
        _result_6 = update_lux(model, Decrement_lux);
    } else if (_match_5 === "Reset") {
        _result_6 = update_lux(model, Reset_lux);
    } else if (true) {
        _result_6 = model;
    } else {
        throw new Error('Non-exhaustive match on ' + JSON.stringify(_match_5));
    }
    return _result_6;
}

function luxView_lux(model) {
    return view_lux(model);
}

