module Dunlop::Loggable
  extend ActiveSupport::Concern

  included do
    has_many :log_entries, as: :loggable, dependent: :destroy, class_name: 'Dunlop::LogEntry'
  end

  def with_nested_logger_and_catch_failed(scope=nil, options={})
    scope ||= caller[0][/`.*'/][1..-2]
    options[:exception_notifier] = true unless options.has_key?(:exception_notifier)
    backtrace = nil
    Dunlop::NestedLogger.scope('empty sandbox', benchmark: false) do
      result = Dunlop::NestedLogger.scope(scope, options) do
        begin
          yield
        rescue => e
          failed!
          ExceptionNotifier.notify_exception(e) if options[:exception_notifier]
          backtrace = Dunlop::LogEntry.exception_to_backtrace(e)
          Dunlop::NestedLogger.error(e.message)
        end
      end
      log_yaml = Dunlop::NestedLogger.flush_as_yaml
      log_entries.create(body: log_yaml, backtrace: backtrace) if log_yaml.present?
      result # return block result
    end
  end

  def with_nested_logger(scope=nil, options={})
    scope ||= caller[0][/`.*'/][1..-2]
    e = nil
    backtrace = nil
    Dunlop::NestedLogger.scope('empty sandbox', benchmark: false) do
      Dunlop::NestedLogger.scope(scope, options) do
        begin
          yield
        rescue => e
          backtrace = Dunlop::LogEntry.exception_to_backtrace(e)
          Dunlop::NestedLogger.error(e.message)
        end
      end
      log_yaml = Dunlop::NestedLogger.flush_as_yaml
      log_entries.create(body: log_yaml, backtrace: backtrace) if log_yaml.present?
    end
    raise e if e
  end

  def logger
    Dunlop::NestedLogger
  end

  def log_state_transition
    log_entries.create(body: "transition to #{state}")
  end

  def log_entry
    Dunlop::LogEntryCreator.new(self)
  end
end
