--rm metest.lua ; wget https://files.rurido.de/raw/136 metest.lua
local sides = require("sides");
--configuration
local cfg = {
    pullStackSize = 1000000, --min size of stacks to pull from me, 0 to disable
    exportSide = sides.top, --export bus side -> top, bottom, front, back, left, right, unknown
    meResponseTime = 5 --time in sec to wait for me to push items
};
--program routine
local c = require("component");
local p = require("process");
local event = require("event");
local thread = require("thread");
local db = nil;
local me = nil;
local ex = nil;
local im = nil;
function main()
    if not c.isAvailable("database") then
        print("Missing component: Database");
        return;
    end
    db = c.database;
    if not c.isAvailable("me_controller") then
       print("Missing component: ME Controller");
       return;
    end
    me = c.me_controller; --primary
    
    if not c.isAvailable("me_exportbus") then
        print("Missing component: ME Exportbus") ;
        return;
    end
    ex = c.me_exportbus --primaryff8484ff8484
    
    --[[
    if not c.isAvailable("me_importbus") then
        print("Missing component: ME Importbus");
        return;
    end
    im = c.me_importbus --primary
    --]]
    
    --init done
    print("ME Network (Connected to ME Network #" .. me.address .. ")");
    print("├──ME Controller");
    print("│  ├──CPUs: " .. #me.getCpus());
    print("│  ├──Energy: " .. me.getEnergyStored() .. " / " .. me.getMaxEnergyStored());
    print("│  ├──Power:");
    print("│  │  ├──Str/Max: " .. me.getStoredPower() .. " / " .. me.getMaxStoredPower());
    print("│  │  ├──In/Out: +" .. me.getAvgPowerInjection() .. " / -" .. me.getAvgPowerUsage());
    print("│  │  └──Idle Use: -" .. me.getIdlePowerUsage());
    print("│  ├──Items: " .. #me.getItemsInNetwork());
    print("│  ├──Fluids: " .. #me.getFluidsInNetwork());
    print("│  ├──Gases: " .. #me.getGasesInNetwork());
    print("│  └──Recipes: " .. #me.getCraftables());
    --print("├──ME Import Bus");
    print("└──ME Export Bus");
    print();
    --[[
    print(" . . . ");
    print("TODO");
    print("DEBUG-ME-MEMBERS");
    for key,value in pairs(me) do
        if type(value) == "function" then
            print(" " .. key .. " -> " .. debug.getinfo(value));
        else
            print(" " .. key .. " -> " .. tostring(value));
        end
        
    end
    --]]
    
    print("PullStackSize: " .. cfg.pullStackSize);
    
    --[[local cleanupThread = thread.create(function()
        event.pull("interrupted");
        print("cleaning up resources");
    end);
    
    
    local workerThread = thread.create(function()--]]
        print("Worker started");
        print("Stop with [CTRL]+[ALT]+[C] (Hard Interrupt)");
        local lastItem = nil;
        while true do
            local foundItem = false;
            
            for key,item in pairs(me.getItemsInNetwork()) do
                os.sleep(0);
                
                if type(item) == "table" and item.size >= cfg.pullStackSize then 
                    
                    print("Next Item: " .. item.label .. " (x" .. item.size .. ")");
                    
                    --printDebug(item);
                    
                    foundItem = true;
                    
                    if trimItem(lastItem) ~= trimItem(item) then
                        ex.setExportConfiguration(cfg.exportSide);
                        print("Cleared Export-Bus configuration");
                        
                        stored = storeInDb(item);
                        
                    else
                        print("Last item == current");
                        stored = true;
                    end
                        
                    if not stored then --db.get(1) == nil then
                        print("Failed to store Item Info to DB");
                    else
                        print("Stored Item Info to DB: " .. db.get(1).label);
                        
                        ex.setExportConfiguration(cfg.exportSide, 1, db.address, 1);
                        print("Set Export-Bus configuration: " .. ex.getExportConfiguration(cfg.exportSide, 1).label);
                        
                        ex.exportIntoSlot(cfg.exportSide, 1);
                        print("Triggered Export");
                        
                        lastItem = item;
                        
                        os.sleep(cfg.meResponseTime);
                        
                    end
                    
                end
            end
            
            if foundItem == false then
                
                print("No Item found using configured properties");
                
                ex.setExportConfiguration(cfg.exportSide);
                print("Cleared Export-Bus configuration");
                
            end
            
        end
    --[[end)
    
    thread.waitForAny({cleanupThread, workerThread});--]]
    os.exit(0); -- closes all remaining threads
    
end
function storeInDb(item)
    for i = 0, 10, 1 do
        db.clear(1);
        local dbItem = trimItem(item);
        me.store(dbItem, db.address, 1, 1);
        if db.get(1) ~= nil then
            print("Stored after " .. i+1 ..  " attempt(s)");
            return true;
        else
            os.sleep(0);--NOP 
            --os.execute("sleep 1");
        end
    end
    
    return false;
end
function trimItem(item)
    
    if item == nil then
       return nil; 
    end
    
    return {
        label = item.label,
        name = item.name,
        damage = item.damage
    };
    
end
function pause()
    print();
    term.write("Press any key to continue ");
    term.read();
    print();  
end
    
function printDebug(val, spaces)
    
    if spaces == nil then
       spaces = ""; 
    end
    
    if string.len(spaces) >= 16 then
        print(spaces .. "RECURSION_LIMIT");
        return; 
    end
    
    if val == nil then
        print(spaces .. "NIL");
        return;
    end
    
    print(spaces .. tostring(val));
    if type(val) == "table" then
        for key,value in pairs(val) do
            print(spaces .. tostring(key) .. " -> " .. tostring(value));
            if type(value) == "function" or type(value) == "table" then
                printDebug(value, "  " .. spaces);
            end
        end
    end
end
p.info().data.signal = function(...)
    print("Caught hard interrupt, terminating...");
    
    ex.setExportConfiguration(cfg.exportSide);
    print("Cleared Export-Bus configuration");
    
    os.exit();
end
main();