# encoding: utf-8
require "extlib"

module ServiceObjects

  module Helpers

    # Features for collecting service messages
    #
    # @note
    #   A target class should **include** the module
    module Messages

      # Translates the text in the current scope with given options
      #
      # The method uses I18n.t library method.
      #
      # @example Returns a translation for symbolic argument
      #   class Test
      #     include ServiceObjects::Helpers::Messages
      #   end
      #
      #   MyClass.new.translate :item
      #   # => translation not found: en.activemodel.messages.models.test.item
      #
      # @example Converts non-symbolic argument to a string.
      #   class Test
      #     include ServiceObjects::Helpers::Messages
      #   end
      #
      #   MyClass.new.translate 1
      #   # => "1"
      #
      # @param  [#to_s] text
      # @param  [Hash] options ({})
      #
      # @return [String]
      def translate(text, options = {})
        return text.to_s unless text.is_a? Symbol
        I18n.t text, Utils::NormalHash.from(options).merge(scope: __scope__)
      end

      # A list of object messages
      #
      # @return [Array<ServiceObjects::Message>]
      def messages
        @messages ||= []
      end

      # Translates the text and adds a new message to the list of {#messages}
      #
      # @example
      #   class MyClass
      #     include ServiceObjects::Helpers::Messages
      #   end
      #
      #   object = MyClass.new
      #   object.add_message type: "foo", text: "bar", priority: 2.5
      #   object.messages
      #   # => [<ServiceObjects::Message type="foo" text="bar" priority=2.5>]
      #
      # @param [Hash] options
      #   the list of options for the message and its translation
      #
      # @option options [#to_s] :text
      #   the text of a new message to be translated via {#translate} method
      # @option options [#to_s] :type
      #   the type of a new message
      # @option options [#to_f] :priority
      #   optional priority fo a new message
      #
      # @return [Array<ServiceObjects::Message>] The updated {#messages}
      def add_message(options)
        params   = Utils::NormalHash.from(options)
        type     = params.delete :type
        priority = params.delete :priority
        text     = translate params.delete(:text), params
        messages << Message.new(text: text, type: type, priority: priority)
      end

      private

      def __scope__
        @__scope__ ||= [:activemodel, :messages, :models, __class_name__.to_sym]
      end

      def __class_name__
        self.class.name.split("::").map(&:snake_case).join("/")
      end

    end # module Messages

  end # module Helpers

end # module Services