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

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

local function packed(...)
  return table.pack(...);
end

local function fakeTerm(width, height)
  local buffer = {};
  local cursorX = 1;
  local cursorY = 1;

  for y = 1, height do
    buffer[y] = {};
    for x = 1, width do
      buffer[y][x] = '.';
    end
  end

  return {
    setCursorPos = function(x, y)
      cursorX = x;
      cursorY = y;
    end,
    write = function(text)
      text = tostring(text);
      for i = 1, #text do
        if buffer[cursorY] and buffer[cursorY][cursorX] then
          buffer[cursorY][cursorX] = string.sub(text, i, i);
        end
        cursorX = cursorX + 1;
      end
    end,
    line = function(y)
      return table.concat(buffer[y], '');
    end,
  };
end

testlib.test('parseArgs accepts basic drawing options', function()
  local carre = createCarre();
  local config = carre.parseArgs(packed('-size', '5', '-x', '2', '-y', '3', '-char', '@', '-fill', '-clear'));

  testlib.assertEquals(config.size, 5);
  testlib.assertEquals(config.x, 2);
  testlib.assertEquals(config.y, 3);
  testlib.assertEquals(config.char, '@');
  testlib.assertEquals(config.fill, true);
  testlib.assertEquals(config.clear, true);
end);

testlib.test('parseArgs rejects invalid sizes', function()
  local carre = createCarre();
  local config, err = carre.parseArgs(packed('-size', '0'));

  testlib.assertEquals(config, nil);
  testlib.assertTrue(string.find(err, 'entier positif', 1, true));
end);

testlib.test('computeSquare centers and clamps the square', function()
  local carre = createCarre();
  local square = carre.computeSquare({ size = 4, char = '#', fill = false }, 10, 6);

  testlib.assertEquals(square.x, 4);
  testlib.assertEquals(square.y, 2);
  testlib.assertEquals(square.size, 4);

  square = carre.computeSquare({ size = 20, x = 99, y = 99, char = '#' }, 7, 5);
  testlib.assertEquals(square.x, 3);
  testlib.assertEquals(square.y, 1);
  testlib.assertEquals(square.size, 5);
end);

testlib.test('computeSquare random keeps explicit character', function()
  local values = { 3, 2, 4 };
  local index = 0;
  local carre = createCarre({
    random = function(minValue, maxValue)
      index = index + 1;
      return math.max(minValue, math.min(maxValue, values[index]));
    end,
  });

  local square = carre.computeSquare({
    random = true,
    char = '@',
    explicit = { char = true },
  }, 10, 8);

  testlib.assertEquals(square.size, 3);
  testlib.assertEquals(square.x, 2);
  testlib.assertEquals(square.y, 4);
  testlib.assertEquals(square.char, '@');
end);

testlib.test('drawSquare renders an outline', function()
  local carre = createCarre();
  local termLib = fakeTerm(8, 6);

  carre.drawSquare(termLib, { x = 2, y = 2, size = 4, char = '#', fill = false });

  testlib.assertEquals(termLib.line(1), '........');
  testlib.assertEquals(termLib.line(2), '.####...');
  testlib.assertEquals(termLib.line(3), '.#  #...');
  testlib.assertEquals(termLib.line(4), '.#  #...');
  testlib.assertEquals(termLib.line(5), '.####...');
end);

testlib.test('drawSquare renders a filled square', function()
  local carre = createCarre();
  local termLib = fakeTerm(6, 5);

  carre.drawSquare(termLib, { x = 2, y = 2, size = 3, char = '*', fill = true });

  testlib.assertEquals(termLib.line(2), '.***..');
  testlib.assertEquals(termLib.line(3), '.***..');
  testlib.assertEquals(termLib.line(4), '.***..');
end);

testlib.run();
