require 'logger'
require 'singleton'

require "tlogger/version"

module Tlogger
  class Error < StandardError; end
  # Your code goes here...

  # 
  # Singleton object to facilitate tag management
  #
  class TloggerConf
    include Singleton
    attr_reader :active_tags, :scoped_tag, :disabled_tags, :auto_tag
    GLOBAL_TAG = :global
    
    def initialize
      @active_tags = [:global]
      @disabled_tags = []
      @disable_all_tags = false
      @auto_tag = false
    end

    def auto_tag_on
      @auto_tag = true
    end

    def auto_tag_off
      @auto_tag = false
    end

    def is_auto_tag_on?
      @auto_tag
    end

    def activate_tag(tag)
      @active_tags << tag
    end

    def deactivate_tag(tag)
      @active_tags.delete(tag)
    end

    def disable_tag(tag)
      if tag.is_a?(Array)
        @disabled_tags += tag
      else
        @disabled_tags << tag
      end
    end

    def all_tags_off
      @disable_all_tags = true
    end

    def enable_tag(tag)
      if tag.is_a?(Array)
        tag.each do |t|
          @disabled_tags.delete(t)
        end
      else
        @disabled_tags.delete(tag)
      end
    end
    
    def is_tag_active?(tag)
      if @disable_all_tags
        false
      else
        @active_tags.include?(tag) and not @disabled_tags.include?(tag)
      end
    end

    def remove_all_active_tags
      @active_tags.clear
    end

    def remove_all_disabled_tags
      @disabled_tags.clear
    end

    def set_scoped_tag(tag)
      @scoped_tag = tag
    end

    def clear_scoped_tag
      @scoped_tag = nil
    end

    def has_scoped_tag?
      if @disable_all_tags
        false
      else
        not @scoped_tag.nil? and not @scoped_tag.empty?
      end
    end

    def self.method_missing(mtd,*args,&block)
      if TloggerConf.instance.respond_to?(mtd)
        TloggerConf.instance.send(mtd,*args,&block)
      else
        super
      end
    end
  end
  # 
  # end TloggerConf singleton
  #

  # 
  # add object like methods to make module a class
  #
  class << self
    attr_accessor :tag
    
    PROXY_MTD = [:debug, :info, :error, :warn]
    def new(*args)
      @tlogger = Logger.new(*args)
      @tag = TloggerConf::GLOBAL_TAG
      self
    end

    def tag=(val)
      @tag = val
      TloggerConf.activate_tag(@tag)
    end

    def method_missing(mtd,*args,&block)
      if @tlogger.respond_to?(mtd)
        if TloggerConf.is_tag_active?(@tag) or TloggerConf.has_scoped_tag?
          if PROXY_MTD.include?(mtd)
            if TloggerConf.has_scoped_tag?
              args[0] = "[#{TloggerConf.scoped_tag}] #{args[0]}"
            else
              if not @tag.nil? and not @tag.empty?
                if @tag == TloggerConf::GLOBAL_TAG
                  if TloggerConf.is_auto_tag_on?
                    args = tag_class(*args)
                  end
                else
                  args[0] = "[#{@tag}] #{args[0]}"
                end
              elsif TloggerConf.is_auto_tag_on?
                args = tag_class(*args)
              end
            end

          end
          
          @tlogger.send(mtd,*args,&block)
        end
      elsif TloggerConf.respond_to?(mtd)
        TloggerConf.send(mtd, *args, &block)
      else
        super
      end
    end

    private
    def tag_class(*args)
      caller.each do |c|
        next if c =~ /tlogger.rb/
        @cal = c
        break
      end
      args[0] = "[#{@cal}] #{args[0]}"
    end
    
  end
  # 
  # end class definition
  #


  def with_tag(tag,&block)
    if block
      TloggerConf.instance.set_scoped_tag(tag)
      block.call
      TloggerConf.instance.clear_scoped_tag
    end
  end
  
end