=begin
  textdomain.rb - GetText::Textdomain

  Copyright (C) 2001-2005  Masao Mutoh
  Copyright (C) 2001-2003  Masahiro Sakai

      Masahiro Sakai    <s01397ms@sfc.keio.ac.jp>
      Masao Mutoh       <mutoh@highway.ne.jp>

  You may redistribute it and/or modify it under the same
  license terms as Ruby.

  $Id: textdomain.rb,v 1.4 2005/08/29 18:24:36 mutoh Exp $
=end

require 'rbconfig'

module GetText
  class TextDomain

    GEM_PATH_RE = /(.*)\/lib$/
    LOCALE_RE = /^([A-Za-z]+)(_[A-Za-z]+)?(\.\S+)?((?:@[^@]*)*)/

    DEFAULT_LOCALE_DIRS = [
      "#{Config::CONFIG['datadir']}/locale/%s/LC_MESSAGES/%s.mo",
      "#{Config::CONFIG['prefix']}/share/locale/%s/LC_MESSAGES/%s.mo",
      "#{Config::CONFIG['prefix']}/local/share/locale/%s/LC_MESSAGES/%s.mo"
    ].uniq

    def initialize(name, path, locale, charset)
      @name, @path = name, path
      @search_files = Array.new

      @locale_dirs = []
      if ENV["GETTEXT_PATH"]
        ENV["GETTEXT_PATH"].split(/,/).each {|i| 
	  @locale_dirs += ["#{i}/%s/LC_MESSAGES/%s.mo", "#{i}/%s/%s.mo"]
	}
      elsif path
        @locale_dirs += ["#{path}/%s/LC_MESSAGES/%s.mo", "#{path}/%s/%s.mo"]
      end

      unless path
	@locale_dirs += DEFAULT_LOCALE_DIRS
	
	if defined? Gem
	  $:.each do |path|
	    if GEM_PATH_RE =~ path
	      @locale_dirs += [
		"#{$1}/data/locale/%s/LC_MESSAGES/%s.mo", 
		"#{$1}/data/locale/%s/%s.mo", 
		"#{$1}/locale/%s/%s.mo"]
	    end
	  end
	end
      end
   
      @mofiles = Hash.new
      set_charset(charset, false)
      set_locale(locale, false)
      load_mo(false)
    
      $stderr.puts "Search path:#{@locale_dirs.inspect}" if $DEBUG
    end
    
    def set_locale(locale, reload = true)
      locale = "C" unless locale
      $stderr.puts "locale:#{locale}" if $DEBUG
      @locales = []
      matched = LOCALE_RE.match(locale)
      if matched and matched.size > 1
        matched = matched.to_a
        matched.shift
        while not matched.empty?
          @locales.push(matched.join(''))
          matched.pop
        end
        @locales.uniq!
      else
        @locales.push(locale)
      end
      load_mo(false) if reload
    end
    
    def gettext(msgid)
      if @mo
	if @mo[msgid]
	  result = @mo[msgid].size > 0 ? @mo[msgid] : msgid
	else
	  result = msgid
	end
      else
	no_mo_file if $DEBUG
        result = msgid
      end
      result
    end

    def ngettext(msgid, msgid_plural, n)
      msg = gettext(msgid + "\000" + msgid_plural)
      if msg.include?("\000")
        ary = msg.split("\000")
        if @mo
          plural = eval(@mo.plural)
          if plural.kind_of?(Numeric)
            msg = ary[plural]
          else
            msg = plural ? ary[1] : ary[0]
          end
        else
          msg = n == 1 ? ary[0] : ary[1]
        end
      end
      msg
    end

    def no_mo_file
      if (@locales.include?("C") || @locales.include?("en"))
	$stderr.puts "\nMO file is not found."
      else
	$stderr.puts "\nMO file is not found in"
	@search_files.each do |fname|
	  $stderr.puts "\t#{fname}"
	end
      end
    end

    def same_property?(name, path, locale, charset)
      @name == name and @path == path and @locales.include?(locale) and @charset == charset
    end
    
    def set_charset(charset, reload = true)
      if charset and charset != ""
        @charset = charset
      else
        @charset = ENV["OUTPUT_CHARSET"] ? ENV["OUTPUT_CHARSET"] : Locale.codeset
      end
      $stderr.puts "GetText::TextDomain#set_charset: charset = #{charset}" if $DEBUG
      load_mo(false) if reload
    end

    attr_reader :charset

    def load_mo(cache = true)
      @mo = nil
      return nil if @locales.include?("C") || @locales.include?("en")
      if cache 
        @locales.each do |locale|
          if @mo = @mofiles[locale]
            return @mo
          end
        end
      end
      @locale_dirs.each do |dir|
	@locales.each{|locale|
	  fname = dir % [locale, @name]
	  @search_files << fname
	  if File.exist?(fname)
	    @mo = MOFile.open(fname, @charset)
	    @mofiles[locale] = @mo
	    break
	  end
	}
      end
      @mo
    end
  end
end
