---@diagnostic disable: undefined-global

local function setup(_, options)
  options = options or {}

  local default_separators = {
    angly = { "", "", "", "" },
    curvy = { "", "", "", "" },
    liney = { "", "", "|", "|" },
    empty = { "", "", "", "" },
  }
  local separators = default_separators[options.separator_style or "angly"]

  local config = {
    separator_styles = {
      separator_open = options.separator_open or separators[1],
      separator_close = options.separator_close or separators[2],
      separator_open_thin = options.separator_open_thin or separators[3],
      separator_close_thin = options.separator_close_thin or separators[4],
      separator_head = options.separator_head or "",
      separator_tail = options.separator_tail or "",
    },
    select_symbol = options.select_symbol or "S",
    yank_symbol = options.yank_symbol or "Y",

    filename_max_length = options.filename_max_length or 24,
    filename_truncate_length = options.filename_truncate_length or 6,
    filename_truncate_separator = options.filename_truncate_separator or "...",

    color = options.color or nil,
    secondary_color = options.secondary_color or nil,
    default_files_color = options.default_files_color
      or th.which.separator_style:fg()
      or "darkgray",
    selected_files_color = options.selected_files_color
      or th.mgr.count_selected:bg()
      or "white",
    yanked_files_color = options.yanked_files_color
      or th.mgr.count_copied:bg()
      or "green",
    cut_files_color = options.cut_files_color or th.mgr.count_cut:bg() or "red",
  }

  local current_separator_style = config.separator_styles

  function Header:count()
    return ui.Line({})
  end

  function Status:mode()
    local mode = tostring(self._tab.mode):upper()

    local style = self:style()
    return ui.Line({
      ui.Span(current_separator_style.separator_head)
        :fg(config.color or style.main:bg()),
      ui.Span(" " .. mode .. " ")
        :fg(th.which.mask:bg())
        :bg(config.color or style.main:bg()),
    })
  end

  function Status:length()
    local h = self._current.hovered
    local len = h and h.cha.len or 0

    local style = self:style()
    return ui.Span(
      current_separator_style.separator_close
        .. " "
        .. ya.readable_size(len)
        .. " "
    )
      :fg(config.color or style.main:bg())
      :bg(config.secondary_color or th.which.separator_style:fg())
  end

  function Status:utf8_sub(str, start_char, end_char)
    local start_byte = utf8.offset(str, start_char)
    local end_byte = end_char and (utf8.offset(str, end_char + 1) - 1) or #str

    if not start_byte or not end_byte then
      return ""
    end

    return string.sub(str, start_byte, end_byte)
  end

  function Status:truncate_name(filename, max_length)
    local base_name, extension = filename:match("^(.+)(%.[^%.]+)$")
    base_name = base_name or filename
    extension = extension or ""

    if utf8.len(base_name) > max_length then
      base_name = self:utf8_sub(base_name, 1, config.filename_truncate_length)
        .. config.filename_truncate_separator
        .. self:utf8_sub(base_name, -config.filename_truncate_length)
    end

    return base_name .. extension
  end

  function Status:name()
    local h = self._current.hovered
    local style = self:style()
    if not h then
      return ui.Line({
        ui.Span(current_separator_style.separator_close .. " ")
          :fg(config.secondary_color or th.which.separator_style:fg()),
        ui.Span("Empty dir"):fg(config.color or style.main:bg()),
      })
    end

    local truncated_name =
      self:truncate_name(h.name, config.filename_max_length)

    return ui.Line({
      ui.Span(current_separator_style.separator_close .. " ")
        :fg(config.secondary_color or th.which.separator_style:fg()),
      ui.Span(truncated_name):fg(config.color or style.main:bg()),
    })
  end

  function Status:files()
    local files_yanked = #cx.yanked
    local files_selected = #cx.active.selected
    local files_cut = cx.yanked.is_cut

    local selected_fg = files_selected > 0 and config.selected_files_color
      or config.default_files_color
    local yanked_fg = files_yanked > 0
        and (files_cut and config.cut_files_color or config.yanked_files_color)
      or config.default_files_color

    local yanked_text = files_yanked > 0
        and config.yank_symbol .. " " .. files_yanked
      or config.yank_symbol .. " 0"

    return ui.Line({
      ui.Span(" " .. current_separator_style.separator_close_thin .. " ")
        :fg(th.which.separator_style:fg()),
      ui.Span(config.select_symbol .. " " .. files_selected .. " ")
        :fg(selected_fg),
      ui.Span(yanked_text .. "  "):fg(yanked_fg),
    })
  end

  function Status:modified()
    local hovered = cx.active.current.hovered

    if not hovered then
      return ""
    end

    local cha = hovered.cha
    local time = (cha.mtime or 0) // 1

    return ui.Span(
      os.date("%Y-%m-%d %H:%M", time)
        .. " "
        .. current_separator_style.separator_open_thin
        .. " "
    ):fg(th.which.separator_style:fg())
  end

  function Status:percent()
    local percent = 0
    local cursor = self._tab.current.cursor
    local length = #self._tab.current.files
    if cursor ~= 0 and length ~= 0 then
      percent = math.floor((cursor + 1) * 100 / length)
    end

    if percent == 0 then
      percent = " Top "
    elseif percent == 100 then
      percent = " Bot "
    else
      percent = string.format(" %2d%% ", percent)
    end

    local style = self:style()
    return ui.Line({
      ui.Span(" " .. current_separator_style.separator_open)
        :fg(config.secondary_color or th.which.separator_style:fg()),
      ui.Span(percent)
        :fg(config.color or style.main:bg())
        :bg(config.secondary_color or th.which.separator_style:fg()),
      ui.Span(current_separator_style.separator_open)
        :fg(config.color or style.main:bg())
        :bg(config.secondary_color or th.which.separator_style:fg()),
    })
  end

  function Status:position()
    local cursor = self._tab.current.cursor
    local length = #self._tab.current.files

    local style = self:style()
    return ui.Line({
      ui.Span(
        string.format(" %2d/%-2d ", math.min(cursor + 1, length), length)
      )
        :fg(th.which.mask:bg())
        :bg(config.color or style.main:bg()),
      ui.Span(current_separator_style.separator_tail)
        :fg(config.color or style.main:bg()),
    })
  end

  Status:children_add(Status.files, 4000, Status.LEFT)
  Status:children_add(Status.modified, 0, Status.RIGHT)
end

return { setup = setup }
