lib/cw_card_utils/decklist_parser/parser.rb



# frozen_string_literal: true

module CwCardUtils
  module DecklistParser
    # Parses a decklist and returns a Deck object.
    class Parser
      attr_reader :deck

      def initialize(decklist, cmc_data_source = nil)
        @decklist = decklist.is_a?(IO) ? decklist.read : decklist
        @deck = Deck.new(cmc_data_source || CwCardUtils.card_data_source)
      end

      def inspect
        "<DecklistParser::Parser: #{@decklist.length}>"
      end

      # Parses the decklist and returns a Deck object.
      def parse
        return @deck if @deck.any?

        sideboard = false

        @decklist.each_line do |line|
          line = line.strip
          next if line.empty?

          sideboard = true if line.downcase.start_with?("sideboard") && (sideboard == false)

          if line.match?(/^(Deck|Sideboard|About|Commander|Creatures|Lands|Spells|Artifacts|Enchantments|Planeswalkers|Mainboard|Maybeboard|Companion)/i)
            next
          end
          next if line.start_with?("#") # skip comment-style lines
          next if line.start_with?("//") # skip comment-style lines
          next if line.start_with?("Name") # skip deck name

          # Match patterns like: "4 Lightning Bolt", "2 Sol Ring (CMM) 452", "1 Atraxa, Praetors' Voice"
          next unless match = line.match(/^(\d+)\s+(.+?)(?:\s+\(.*?\)\s+\d+)?$/) # rubocop:disable Lint/AssignmentInCondition

          count = match[1].to_i
          name = match[2].strip
          target = sideboard ? :sideboard : :mainboard
          @deck.add({ count: count, name: name }, target)
        end

        @deck
      end

    end
  end
end