local createVersion = require('/apis/libversion');

local args = table.pack(...);

-- Tete de mouton style Minecraft: un carre de laine avec un visage carre au centre.
-- Les lettres sont des pixels de couleur. Le point est le fond.
local SHEEP = {
  '..WWWWWWWWWWWW..',
  '.WWwwWWwwWWwwWW.',
  'WWwwWWwwWWwwWWww',
  'Wwwwwwwwwwwwwwww',
  'WWwwKKKKKKKKwwWW',
  'WwwwKkkkkkkKwwww',
  'WWwwKfkkkkfKwwWW',
  'WwwwKfkkkkfKwwww',
  'WWwwKkkMMkkKwwWW',
  'WwwwKkkmmkkKwwww',
  'WWwwKkkkkkkKwwWW',
  'WwwwKKKKKKKKwwww',
  'WWwwwwwwwwwwwwWW',
  'WwWWwwWWwwWWwwWw',
  '.WWwwWWwwWWwwWW.',
  '..WWWWWWWWWWWW..',
};

local THEMES = {
  classic = {
    title = 'Mouton Minecraft',
    background = colors.black,
    text = colors.white,
    palette = {
      ['.'] = colors.black,
      W = colors.white,
      w = colors.lightGray,
      K = colors.gray,
      k = colors.lightGray,
      f = colors.black,
      M = colors.gray,
      m = colors.black,
    },
  },
  rose = {
    title = 'Mouton Rose',
    background = colors.black,
    text = colors.pink,
    palette = {
      ['.'] = colors.black,
      W = colors.pink,
      w = colors.magenta,
      K = colors.white,
      k = colors.lightGray,
      f = colors.black,
      M = colors.pink,
      m = colors.black,
    },
  },
  nuage = {
    title = 'Mouton Nuage',
    background = colors.lightBlue,
    text = colors.white,
    palette = {
      ['.'] = colors.lightBlue,
      W = colors.white,
      w = colors.lightGray,
      K = colors.gray,
      k = colors.white,
      f = colors.black,
      M = colors.lightGray,
      m = colors.black,
    },
  },
  arcenciel = {
    title = 'Mouton Arc-en-ciel',
    background = colors.black,
    text = colors.yellow,
    rainbow = true,
    palette = {
      ['.'] = colors.black,
      K = colors.white,
      k = colors.lightGray,
      f = colors.black,
      M = colors.pink,
      m = colors.black,
    },
  },
};

local THEME_NAMES = { 'classic', 'rose', 'nuage', 'arcenciel' };
local RAINBOW = {
  colors.red,
  colors.orange,
  colors.yellow,
  colors.lime,
  colors.cyan,
  colors.blue,
  colors.purple,
  colors.magenta,
};

local function printUsage()
  print('mouton usage:');
  print();
  print('  mouton');
  print('  mouton <theme>');
  print('  mouton --theme <theme>');
  print('  mouton --random');
  print('  mouton --version');
  print('  mouton --help');
  print();
  print('themes: classic, rose, nuage, arcenciel');
end

local function drawRun(x, y, len, color)
  term.setBackgroundColor(color);
  term.setCursorPos(x, y);
  term.write(string.rep(' ', len));
end

local function themeNamesText()
  return table.concat(THEME_NAMES, ', ');
end

local function parseArgs(argv)
  local selectedTheme = 'classic';
  local selectedExplicitly = false;
  local randomTheme = false;
  local index = 1;

  while index <= argv.n do
    local arg = argv[index];

    if arg == '--random' or arg == '-random' then
      if selectedExplicitly then
        return nil, '--random ne peut pas etre combine avec un theme';
      end
      randomTheme = true;
    elseif arg == '--theme' or arg == '-theme' then
      if randomTheme or selectedExplicitly then
        return nil, arg .. ' ne peut pas etre combine avec un autre theme';
      end
      index = index + 1;
      selectedTheme = argv[index];
      if selectedTheme == nil then
        return nil, 'theme manquant apres ' .. arg;
      end
      selectedExplicitly = true;
    elseif THEMES[arg] ~= nil then
      if randomTheme or selectedExplicitly then
        return nil, arg .. ' ne peut pas etre combine avec un autre theme';
      end
      selectedTheme = arg;
      selectedExplicitly = true;
    else
      return nil, 'option ou theme inconnu: ' .. tostring(arg);
    end

    index = index + 1;
  end

  if randomTheme then
    math.randomseed(os.epoch('utc'));
    selectedTheme = THEME_NAMES[math.random(1, #THEME_NAMES)];
  end

  if THEMES[selectedTheme] == nil then
    return nil, 'theme inconnu: ' .. tostring(selectedTheme)
      .. ' (disponibles: ' .. themeNamesText() .. ')';
  end

  return THEMES[selectedTheme];
end

local function tokenColor(theme, token, row, col)
  if theme.rainbow and (token == 'W' or token == 'w') then
    -- Pour le mouton arc-en-ciel, seules les boucles de laine changent de couleur.
    return RAINBOW[((row + col) % #RAINBOW) + 1];
  end

  return theme.palette[token] or theme.background;
end

local function drawSheep(theme)
  local width, height = term.getSize();
  local pixelW = math.max(1, math.floor(width / 20));
  local pixelH = math.max(1, math.floor(height / 20));

  if pixelW < 2 and width >= #SHEEP[1] * 2 then pixelW = 2; end
  if pixelW > 4 then pixelW = 4; end
  if pixelH > 2 then pixelH = 2; end

  local artW = #SHEEP[1] * pixelW;
  local artH = #SHEEP * pixelH;
  local startX = math.max(1, math.floor((width - artW) / 2) + 1);
  local startY = math.max(1, math.floor((height - artH) / 2) + 1);

  term.setBackgroundColor(theme.background);
  term.setTextColor(theme.text);
  term.clear();

  for row = 1, #SHEEP do
    for sy = 0, pixelH - 1 do
      local y = startY + ((row - 1) * pixelH) + sy;
      local col = 1;

      while col <= #SHEEP[row] do
        local token = SHEEP[row]:sub(col, col);
        local run = 1;
        local color = tokenColor(theme, token, row, col);

        while col + run <= #SHEEP[row]
          and SHEEP[row]:sub(col + run, col + run) == token
          and tokenColor(theme, token, row, col + run) == color do
          run = run + 1;
        end

        drawRun(startX + ((col - 1) * pixelW), y, run * pixelW, color);
        col = col + run;
      end
    end
  end

  term.setBackgroundColor(theme.background);
  term.setTextColor(theme.text);

  if height >= startY + artH then
    term.setCursorPos(math.max(1, math.floor((width - #theme.title) / 2) + 1), startY + artH + 1);
    term.write(theme.title);
  end

  term.setCursorPos(1, height);
end

local command = args[1];

if command == '-help' or command == '--help' or command == 'help' then
  printUsage();
  return;
end

if command == '-version' or command == '--version' or command == 'version' then
  print('v' .. createVersion().forSelf());
  return;
end

local theme, err = parseArgs(args);
if not theme then
  print(err);
  print('utilise: mouton -help');
  return;
end

drawSheep(theme);
