# frozen_string_literal: true

require_relative 'abstract_handler'

module Hypertube
  module Core
    module Handler
      class SetInstanceFieldHandler < Hypertube::Core::Handler::AbstractHandler
        def initialize
          @required_parameters_count = 3
        end

        def process(command)
          set_instance_field(command)
        end

        def set_instance_field(command)
          validate(command, @required_parameters_count, self.class.name)

          instance = command.payload[0]
          field_name = command.payload[1]
          new_value = command.payload[2]

          begin
            if instance.instance_variable_defined?(field_name)
              instance.instance_variable_set(field_name, new_value)
            else
              raise NameError, "Field #{field_name} not found"
            end
          rescue NameError, NoMethodError => e
            fields = instance.instance_variables

            value_type = new_value.nil? ? 'null' : new_value.class.name
            class_name = instance.class.name
            message = "Failed to set value of type #{value_type} for #{field_name} in class #{class_name}.\nAvailable public instance variables:\n"
            fields.each { |field_iter| message += "#{field_iter}\n" }
            message += "Root error message: #{e.message}"
            raise ArgumentError, message
          end
          instance
        end
      end
    end
  end
end
