local createLibTest = require('/apis/libtest');

local testlib = createLibTest({ ... });

local function runStartupWithStubs(settingValues)
  settingValues = settingValues or {};
  local settingIndex = 0;
  local calls = {
    rebooted = false,
    shutdown = false,
    shellRuns = {},
    prints = {},
  };

  local env = setmetatable({
    require = require,
    fs = {
      exists = function(path)
        return path ~= '/trapos/manifest.json' and fs.exists(path);
      end,
      delete = function() end,
    },
    os = {
      reboot = function()
        calls.rebooted = true;
      end,
      shutdown = function()
        calls.shutdown = true;
      end,
      sleep = function() end,
    },
    settings = {
      get = function(key)
        if key ~= 'trapos.on_session_end' then return nil; end
        settingIndex = settingIndex + 1;
        if type(settingValues) == 'table' then
          return settingValues[settingIndex] or settingValues[#settingValues];
        end
        return settingValues;
      end,
    },
    parallel = {
      waitForAny = function(firstFn)
        firstFn();
      end,
    },
    print = function(message)
      calls.prints[#calls.prints + 1] = tostring(message);
    end,
    shell = {
      path = function()
        return '/rom/programs';
      end,
      run = function(program)
        calls.shellRuns[#calls.shellRuns + 1] = program;
        return true;
      end,
      setPath = function() end,
    },
  }, { __index = _G });
  env._G = env;

  local chunk, loadErr = loadfile('/startup/boot.lua', 't', env);
  if not chunk then
    error(loadErr, 0);
  end

  local ok, err = pcall(chunk);
  if not ok then
    error(err, 0);
  end

  return calls;
end

testlib.test('shell exit shuts down by default', function()
  local calls = runStartupWithStubs();

  testlib.assertEquals(calls.shellRuns[1], '/programs/motd.lua');
  testlib.assertEquals(calls.shellRuns[2], 'shell');
  testlib.assertEquals(calls.shutdown, true);
  testlib.assertEquals(calls.rebooted, false);
  for _, message in ipairs(calls.prints) do
    testlib.assertTrue(
      not string.find(message, 'Servers stopped', 1, true),
      'startup should not print a forced reboot message'
    );
  end
end);

testlib.test('shell exit reboots when policy is reboot', function()
  local calls = runStartupWithStubs('reboot');

  testlib.assertEquals(calls.shellRuns[1], '/programs/motd.lua');
  testlib.assertEquals(calls.shellRuns[2], 'shell');
  testlib.assertEquals(calls.shutdown, false);
  testlib.assertEquals(calls.rebooted, true);
end);

testlib.test('shell exit relaunches until policy changes', function()
  local calls = runStartupWithStubs({ 'relaunch', 'shutdown' });

  testlib.assertEquals(calls.shellRuns[1], '/programs/motd.lua');
  testlib.assertEquals(calls.shellRuns[2], 'shell');
  testlib.assertEquals(calls.shellRuns[3], 'shell');
  testlib.assertEquals(calls.shutdown, true);
  testlib.assertEquals(calls.rebooted, false);
end);

testlib.run();
