require 'logger'

module ServicePacker
  class Base
    module InstanceMethods
      def initialize(*args)
        @_pass_in_arguments = {}

        super(*args)
      end

      def method_missing(name, *args, &block)
        super(name, *args, &block) unless @_pass_in_arguments.include? name
        @_pass_in_arguments[name.to_sym]
      end

      # DO NOT CALL THIS METHODS UNLESS IF YOU ARE DEFINITELY KNOWN WHAT YOU DID
      # This method is for pass-in-arguments temporarily
      def __set_arguments(kwargs)
        @_pass_in_arguments.merge!(kwargs)
      end

      def __clear_arguments
        @_pass_in_arguments = {}
      end
    end

    module ClassMethods
      def inherited(base)
        ServicePackerStore.register(base)
        base.prepend InstanceMethods

        super
      end

      def service_packer
        ServicePackerStore.fetch(self)
      end

      def setup(method_name, *args, &block)
        kwargs = args[-1].is_a?(Hash) ? args[-1] : {}
        params = kwargs[:params] || []
        service = service_packer
        service.setup_method(method_name) { service.instance_exec(&block) }
        define_method(method_name) do |*args|
          raise ArgumentError, "wrong number of arguments (given #{args.size}, expected #{params.size})" if args.size != params.size
          service.invoke(self, method_name, params, *args)
        end
      end

      def setup_common_validation(&block)
        service = service_packer
        service.common_validation_define(&block)
      end

      def setup_common_callback(&block)
        service = service_packer
        service.common_callback_define(&block)
      end
    end

    extend ClassMethods

  end
end
