# Copyright (C) 2003-2005 Kouichirou Eto, All rights reserved.

$LOAD_PATH << "../../lib" unless $LOAD_PATH.include?("../../lib")

module Qwik
  class SiteMember
    include Enumerable

    def initialize(config, site)
      @config = config
      @site = site
      @quickml_member = QuickMLMember.new(@config, @site)
    end

    def exist?(user)
      return true if exist_qwik_members?(user)
      return true if @quickml_member.exist?(user)
      false
    end

    def exist_qwik_members?(user)
      return false if db_page.nil?
      db.exist?(user)
    end

    def add(user, invite=nil)
      db.add(user, invite)
    end
    alias invite add

    def remove(user)
      db.remove(user) if db_page
    end

    def list(obf=true)
      ar = []
      ar += db.hash.keys.to_a if db_page
      ar += @quickml_member.list
      ar = ar.uniq
      if obf && @site.is_open?
	ar = ar.map {|u|
	  MailAddress.new(u).obfuscate
	}
      end
      ar
    end

    def each
      list.each {|u|
	yield u
      }
    end

    private

    def db_page
      k = "SiteMember"
      return @site[k] if @site.exist?(k)
      k = "_"+k
      return @site[k] if @site.exist?(k)
      return @site.create(k)
    end

    def db
      page = db_page
      page.wikidb
    end
  end

  class QuickMLMember # QuickML compatible
    include Enumerable

    def initialize(config, site)
      @config = config
      @site = site
      @str = nil
      @ar = []
      check_new
    end

    def list
      check_new
      @ar
    end

    def exist?(user)
      list.include?(user)
    end

    private

    def check_new
      file = @site.dir.path+",members"
      return unless file.exist?
      str = file.open("rb"){|f| f.read }
      return if str == @str
      @str = str
      @ar = []
      @str.each {|line|
	firstchar = line[0, 1]
	# next if ["#", ";"].include?(firstchar)
	next if firstchar == "#" || firstchar == ";"
	k, v = line.chomp.split
	next if k.nil?
	@ar << k
      }
    end
  end
end

if $0 == __FILE__
  $LOAD_PATH << "../../lib" unless $LOAD_PATH.include?("../../lib")
  require "qwik/test-common"
  $debug = true
end

if $debug
  class TC_SiteMember < Test::Unit::TestCase
    include TestSession

    def test_member
      user = "user@e.com"
      member = @site.member
      page = @site.create("_SiteMember")
      assert_equal(false, member.exist?(user))
      page.store("user@e.com");	assert(!member.exist?(user))
      page.store(",user@e.com");	assert(member.exist?(user))
      page.store(",user@e.com,");	assert(member.exist?(user))
      page.store(",user@e.com,a");assert(member.exist?(user))
      page.store(",user@e.com,a,");assert(member.exist?(user))
      member.remove(user);		assert(!member.exist?(user))
      assert_equal("", page.load)
      member.add(user);			assert(member.exist?(user))
      guest = "guest@example.com"
      member.invite(guest, user);	assert(member.exist?(guest))
      assert_equal(",user@e.com,\n,guest@example.com,user@e.com\n",
		   page.load)
      assert_equal(["user@e.com", "guest@example.com"], member.list)
      member.remove(guest);		assert(!member.exist?(guest))
      @site.delete("_SiteMember");	assert(!member.exist?(user))
      assert_equal([], member.list)

      # test_quickml_member
      assert(!member.exist?(user))
      store("user@e.com");	assert(member.exist?(user))
      assert_equal(["user@e.com"], member.list)
      store("# user@e.com");	assert(!member.exist?(user))
      store("; user@e.com");	assert(!member.exist?(user))
      store("");			assert(!member.exist?(user))
      assert_equal([], member.list)

      # test_obfuscate
      page = @site["_SiteConfig"]
      assert_match(/:open:false/, page.load)
      assert_equal(false, @site.is_open?)
      page.store(":open:true")
      assert_equal(":open:true", page.load)
      assert_equal(true, @site.is_open?)

      member.add(user)
      member.add("guest@example.com")
      assert_equal(["user@e...", "guest@e..."], member.list)
    end

    def store(content) # quickml_member
      (@dir+",members").open("wb"){|out|
	out.puts(content)
      }
    end
  end
end
