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

$LOAD_PATH << "../../lib" unless $LOAD_PATH.include?("../../lib")
require "qwik/util-path"

module Qwik
  class AlreadyExist < StandardError; end
  class CanNotUseJapaneseCharacter < StandardError; end
  class AlreadyDeleted < StandardError; end
  class FailedToDelete < StandardError; end
  class CanNotAccessParentDirectory < StandardError; end

  module AttachModule
    def path(filename="")
      raise CanNotAccessParentDirectory if filename.to_s.include?("..")
      @attach_path.check_directory
      @attach_path+filename
    end

    def exist?(filename)
      path(filename).exist?
    end

    def put(filename, content, overwrite=nil)
      if !overwrite
	raise AlreadyExist if path(filename).exist?
      end

      check_kanji_character(filename)

      @attach_path.check_directory
      path(filename).open("wb"){|f|
	f.print content
      }
    end

    def each
      return unless @attach_path.directory?
      @attach_path.each_entry {|file|
	next if file.to_s[0] == ?.
	next if file.directory?
	yield(file.to_s)
      }
    end

    def delete(filename)
      raise AlreadyDeleted unless path(filename).exist?
      path(filename).unlink
      raise FailedToDelete if path(filename).exist?
    end

    private

    def check_kanji_character(filename)
      filename.each_byte {|byte|
	if 0x7f < byte || byte == ?\e
	  raise CanNotUseJapaneseCharacter
	end
      }
    end
  end

  class PageFiles
    include Enumerable
    include AttachModule

    def initialize(site_dir, key)
      @site_dir = site_dir
      @key = key
      @attach_path = @site_dir.path+"#{@key}.files"
    end
  end
end

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

if $debug
  class TC_PageFiles < Test::Unit::TestCase
    def setup
      @dir = "./test/".path
      @dir.setup
      @files = Qwik::PageFiles.new(@dir.to_s, "1")
    end

    def teardown
      @dir.teardown
    end

    def assert_exist(e, s)
      assert_equal(e, @files.exist?(s))
    end

    def test_site_attach
      d = @dir+".attach"
      d.teardown if d.exist?

      assert_exist(false, "t.txt")

      # test put
      @files.put("t.txt", "t")
      assert_exist(true, "t.txt")

      # test get
      path = @files.path("t.txt")
      assert_equal("./test/1.files/t.txt", path.to_s)
      assert_equal("t", path.open {|f| f.read })

      # test delete
      @files.delete("t.txt")
      assert_exist(false, "t.txt")

      # test_security
      path = @files.path("t/t.txt") # ok
      assert_raise(Qwik::CanNotAccessParentDirectory) {
	path = @files.path("../t.txt") # bad
      }
    end
  end
end
