module TxCatcher

  class Logger

    LOG_LEVELS = {
      info: 1,
      warn: 2,
      error: 3,
      fatal: 4,
      unknown: 5
    }

    attr_accessor :reporters

    def initialize(log_file: "txcatcher.log", error_file: "error.log", error_log_delimiter: "\n\n", reporters: [:logfile, :stdout, :sentry])
      @log_file_name       = log_file
      @error_log_file_name = error_file
      @error_log_delimiter = error_log_delimiter
      @reporters           = reporters
    end


    def report(message, log_level=:info, data: nil, timestamp: false)
      @reporters.each do |out|
        if LOG_LEVELS[log_level] >= LOG_LEVELS[Config["logger"]["#{out}_level"].to_sym]
          send("report_to_#{out}", message, log_level, data: data, timestamp: timestamp)
        end
      end
    end

    private

      def report_to_stdout(message, log_level, data: nil, timestamp: timestamp)
        $stdout.print prepare_message(message, timestamp: timestamp) + "\n"
        $stdout.print "  additional data: #{data.to_s}\n" if data
        $stdout.print(@error_log_delimiter) if LOG_LEVELS[log_level] >= LOG_LEVELS[:error]
      end

      def report_to_logfile(message, log_level, data: nil, timestamp: true) # always gonna be forcing timestamp to be true here
        fn = LOG_LEVELS[log_level] >= LOG_LEVELS[:error] ? @error_log_file_name : @log_file_name
        fn = TxCatcher::Config.config_dir + "/#{fn}"

        File.open(fn, "a") do |f|
          f.print "#{prepare_message(message, timestamp: true)}\n"
          f.print "  additional data: #{data.to_s}\n" if data
          f.print(@error_log_delimiter) if LOG_LEVELS[log_level] >= LOG_LEVELS[:error]
        end
      end

      def report_to_sentry(e, log_level, data: nil, timestamp: timestamp)
        return unless TxCatcher::Config["logger"]["sentry_dsn"]
        data ||= {}
        data.merge!(environment: Config["environment"], host: Config["host"], currency: Config["currency"])
        Raven.tags_context data
        e.kind_of?(Exception) ? Raven.capture_exception(e) : Raven.capture_message(e)
      end

      def prepare_message(e, timestamp: false)
        result = if e.kind_of?(Exception)
          result =  e.class.to_s + " - "
          result += e.to_s + "\n"
          result += e.message + "\n\n" if e.message != e.to_s
          result += (e.backtrace&.join("\n") || "[no backtrace]")
          result
        else
          e
        end
        result = "[#{Time.now}] #{result}" if timestamp
        result
      end


  end

end
