local lfs = require "lfs"
local json = require "dkjson"

local _CRIT_KEYS = {"A", "B", "C", "D", "E"}

local function process_values(rest, condition)
  -- Get the +XH (with X being a number)
  if not rest then
    return {}
  end

  local damage = rest:match("%+(%d*)H")

  -- π = mustparry
  local mustparry = false
  if rest:match("– π") then
    mustparry = 1
  end
  if rest:match("– (%d)π") then
    mustparry = rest:match("– (%d*)π")
  end
  local mustparry_duration = false
  local mustparry_value = false
  local duration, value = rest:match("– (%d?)%((π%-?%d+)%)")
  if duration or value then
    mustparry_duration = tonumber(duration) or 1
    mustparry_value = tonumber(value)
  end

  -- ∑ = stunned
  local stunned = false
  local match = rest:match("– (%d*)∑")
  if match then
    stunned = tonumber(match) or 1
  end

  -- ∏ = cannot parry
  local cannot_parry = false
  match = rest:match("– (%d*)∑?∏")
  if match then
    cannot_parry = tonumber(match) or 1
  end
  match = rest:match("– (%d*)∏")
  if match then
    cannot_parry = tonumber(match) or 1
  end

  -- ∫ = wounds per rounds  
  local wounds_per_round = false
  match = rest:match("– (%d?)∫")
  if match then
    wounds_per_round = tonumber(match) or 1
  end

  -- Round penalty 

  local round_penalty_duration = false
  local nbRounds, round_penalty_value = rest:match("– (%d?)%((%-?%d+)%)")
  if nbRounds or round_penalty_value then
    round_penalty_duration = tonumber(nbRounds) or 1
    round_penalty_value = tonumber(round_penalty_value)
  end

  -- Round bonus
  local round_bonus_duration = false
  local nbRounds, round_bonus_value = rest:match("– (%d?)%((%+?%d+)%)")
  if nbRounds or round_bonus_value then
    round_bonus_duration = tonumber(nbRounds) or 1
    round_bonus_value = tonumber(round_bonus_value)
  end

  print(rest, damage, mustparry, stunned, cannot_parry, wounds_per_round, round_penalty_duration, round_penalty_value,
    round_bonus_duration, round_bonus_value)
  return {
    condition = condition or "none",
    damage = damage,
    mustparry = mustparry,
    stunned = stunned,
    cannot_parry = cannot_parry,
    wounds_per_round = wounds_per_round,
    round_penalty_duration = round_penalty_duration,
    round_penalty_value = round_penalty_value,
    round_bonus_duration = round_bonus_duration,
    round_bonus_value = round_bonus_value,
    mustparry_duration = mustparry_duration,
    mustparry_value = mustparry_value
  }
end

local all_criticals = {}

local function process_line(line)
  local effects = {}
  -- Get description (ie all text befire the first \n)
  local desc = line:match("([^\n]+)")
  -- Get the rest of the text
  local rest = line:match("\n(.+)")
  if rest then
    if rest:match("with ") then
      local reasonwith, with, reasonwithout, without = rest:match("(with[^:]*): ([^w]+)(w/o[^:]*): (.+)")
      print("SPLITTEW WITH", desc)
      effects[1] = process_values(with, reasonwith)
      effects[2] = process_values(without, reasonwithout)
    else
      effects[1] = process_values(rest)
    end
  else
    print("NO REST", desc)
  end
  return desc, effects
end

-- Loop thru all JSON files in the criticals_data directory
for file in lfs.dir("./") do
  if file:match("json$") then
    local json_file = io.open("./" .. file, "r")
    local json_data = json_file:read("*a")
    json_file:close()

    local crit = {
      name = string.match(file, "([%w_]+).json"),
      criticals = {}
    }

    local rows = json.decode(json_data)
    if not rows then
      print("Error decoding JSON file: " .. file)
      return
    end
    for _, c in ipairs(rows) do
      local new_crit = {
        score = c.Score,
        isCreature = false,
        levels = {}
      }

      -- Process tables with A-E criticals
      local isWeapon = true
      for _, key in ipairs(_CRIT_KEYS) do
        local line = c[key]
        if not line then
          isWeapon = false
          break
        end

        local desc, effects = process_line(line)
        new_crit.levels[key] = {
          key = key,
          description = desc,
          effects = effects
        }

      end

      -- Creatures table       
      if not isWeapon then
        new_crit.isCreature = true
        for key, line in pairs(c) do
          if key ~= "Score" then
            local desc, effects = process_line(line)
            new_crit.levels[key] = {
              key = key,
              description = desc,
              effects = effects
            }
          end
        end
      end

      table.insert(crit.criticals, new_crit)
    end

    all_criticals[crit.name] = crit
  end
end

-- Convert to JSON
local json_data = json.encode(all_criticals, {
  indent = true
})
print(json_data)

-- Write the whole json_data to a single file
local json_file = io.open("criticals.json", "w+")
json_file:write(json_data)
json_file:close()

