-- main.lua —— 使用流式文件操作的安全主逻辑

_ENCRYPT_ = 0

VT_LW = 1
VT_RW = 2

function on_init()
    dofile('file.lua')
    set_string(VT_LW, 0x1510, 'newfile')
    set_string(VT_LW, 0x1520, 'Hello HMI!')
    set_uint16(VT_LW, 0x1507, 0)
end

function get_extension(filename)
    local dot = string.find(filename, ".", 1, true)
    if dot then
        return string.sub(filename, 1, dot-1), string.sub(filename, dot+1):lower()
    end
    return filename, "未知"
end

function on_list_dir(path, filename, type, fsize)
    local msg
    if type == 0 then
        msg = filename .. ";文件夹;;"
    else
        local sz
        if fsize >= 1024^3 then
            sz = string.format("%.2fG", fsize / 1024^3)
        elseif fsize >= 1024^2 then
            sz = string.format("%.2fM", fsize / 1024^2)
        elseif fsize >= 1024 then
            sz = string.format("%.2fKB", fsize / 1024)
        else
            sz = fsize .. "byte"
        end
        local name, ext = get_extension(filename)
        msg = name .. ";" .. ext .. ";" .. sz .. ";"
    end
    record_write_string(2, msg)
end

function on_copy_file_process(status, filesize, transfersize)
    if status == 0 then
        set_uint16(VT_LW, 0x1507, 3)
    elseif status == 1 then
        local p = math.floor(transfersize * 100 / filesize)
        set_uint16(VT_LW, 0x1506, p)
        refresh_screen()
    elseif status == 2 then
        set_uint16(VT_LW, 0x1506, 100)
        set_uint16(VT_LW, 0x1507, 2)
        refresh_screen()
    end
end

-- 全局行缓冲区（仅缓存未完成的行）
local g_line_buffer = ""

function on_update(slave, vtype, addr)
    if vtype ~= VT_LW then return end

    -- 读取文本文件（流式按行显示）
    if addr == 0x1501 
    then
        local idx = get_uint16(vtype, addr)
        if idx == 0 then return end

        local path = (idx == 1) and "1:/test1.txt" or "1:/test2.txt"
        record_clear(0)

        g_line_buffer = ""  -- 重置行缓冲

        file.read_stream(path, function(chunk, offset, is_last)
            -- 将字节块转为字符串
            local str = ""
            for _, b in ipairs(chunk) do str = str .. string.char(b) end

            -- 拼接到行缓冲
            g_line_buffer = g_line_buffer .. str

            -- 按行分割
            local lines = my_split(g_line_buffer, "\n")
            g_line_buffer = lines[#lines]  -- 保留不完整行

            -- 显示完整行
            for i = 1, #lines - 1 
            do
                if #lines[i] > 0 then record_write_string(0, lines[i]) end
            end

            return true
        end)

        -- 显示最后一行（如果非空）
        if string.len(g_line_buffer) > 0 then record_write_string(0, g_line_buffer) end

    -- 读取二进制文件（流式 16 字节/行）
    elseif addr == 0x1502 
    then
        local idx = get_uint16(vtype, addr)
        if idx == 0 then return end

        local path = (idx == 1) and "1:/test1.bin" or "1:/test2.bin"
        record_clear(1)

        -- 重置全局缓冲区
        g_byte_buffer = {}

        file.read_stream(path, function(chunk, offset, is_last)
            -- 将当前 chunk 的所有字节追加到缓冲区
            for _, b in ipairs(chunk) do
                table.insert(g_byte_buffer, b)
                
                -- 每满 16 字节，提交一行
                if #g_byte_buffer >= 16 then
                    local line = {}
                    for i = 1, 16 do
                        line[i] = g_byte_buffer[i]
                    end
                    record_write_data(1, line)
                    
                    -- 移除已提交的 16 字节
                    for i = 1, 16 do table.remove(g_byte_buffer, 1) end
                end
            end
            
            return true
        end)

        -- 【可选】处理文件末尾不足 16 字节的数据 例如：用 0 填充或单独显示
        if #g_byte_buffer > 0 
        then
             while #g_byte_buffer < 16 do table.insert(g_byte_buffer, 0) end
             record_write_data(1, g_byte_buffer)
         end



    -- 写入文件（使用小块写入）
    elseif addr == 0x1503 
    then
        local mode = get_uint16(vtype, addr)
        if mode ~= 1 and mode ~= 2 then return end

        local name = get_string(VT_LW, 0x1510)
        local msg  = get_string(VT_LW, 0x1520)
        if not name or #name == 0 or not msg then return end

        local path = "1:/" .. name .. ".txt"-- 直接写入（msg 应为小字符串）
        local ret = file.write_chunk(path, msg..'\n',  mode) 

        refresh_screen()

    -- 列出文件
    elseif addr == 0x1504 
    then
        if get_uint16(vtype, addr) == 1 
        then
            record_clear(2)
            list_dir("1:")
        end

    -- 文件操作
    elseif addr == 0x1505 
    then
        local mode = get_uint16(vtype, addr)
        if mode == 1 then
            if file.exists("1:/1.txt") 
            then
                file_copy("1:/1.txt", "1:/1_copy.txt")
            else
                set_uint16(VT_LW, 0x1507, 1)
            end
            mkdir('1:/test')

        elseif mode == 2 
        then
            file_delete("1:/test")

            if file.exists("1:/1_copy.txt") 
            then
                file_delete("1:/1_copy.txt")
                if not file.exists("1:/1_copy.txt") 
                then
                    set_uint16(VT_LW, 0x1507, 4)
                else
                    set_uint16(VT_LW, 0x1507, 5)
                end
            else
                set_uint16(VT_LW, 0x1507, 1)
            end
        end


        refresh_screen()
    end
end

function on_run(screen) end
function on_press(state, x, y) end
function on_draw(screen_id, control_id) end