#--
# =============================================================================== 
# Copyright (c) 2005,2006,2007 Christopher Kleckner
# All rights reserved
#
# This file is part of the Rio library for ruby.
#
# Rio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Rio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Rio; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
# =============================================================================== 
#++
#
# To create the documentation for Rio run the command
#  ruby build_doc.rb
# from the distribution directory.
#
# Suggested Reading
# * RIO::Doc::SYNOPSIS
# * RIO::Doc::INTRO
# * RIO::Doc::HOWTO
# * RIO::Doc::EXAMPLES
# * RIO::Rio
#

require 'zip/zip'
require 'zip/zipfilesystem'
require 'delegate'

module RIO
  module ZipFile
    module Wrap
      module Stream
        class Input < DelegateClass(::Zip::ZipInputStream)
          def initialize(zipstream)
            @closed = false
            super
          end
          def close()
            super
            @closed = true
          end
          def closed?() @closed end
        end
        class Output < DelegateClass(::Zip::ZipOutputStream)
          def initialize(zipstream)
            @closed = false
            @zipstream = zipstream
            super
          end
          def close()
            p "CLOSE: #{@zipstream.inspect}"
            #p self.__getobj__.methods.sort
            super
            @closed = true
          end
        end
        class Dir < DelegateClass(::Zip::ZipFileSystem::ZipFsDirIterator)
        end
        class Root 
          def initialize(zipfile)
            @zipfile = zipfile
            @infs = RIO::ZipFile::InFile::FS.new(@zipfile)
            #puts @zipfile.methods.sort
            @topents = get_topents_
            @entidx = 0
          end
          def get_topents_
            topents = {}
            @zipfile.entries.map{ |ent|
              top = ent.to_s.match(%r|^(/?[^/]+(/)?)|)[1]
              topents[top] = 1 unless topents.has_key?(top)
            }
            topents.keys.map{ |v| rio(RIO::Path::RL.new(v.to_s,{:fs => @infs})) }
          end
          def read
            return nil if @entidx >= @topents.size
            @entidx += 1
            @topents[@entidx-1]
          end
          def each(&block)
            get_topents_.each { |ent|
              yield ent
            }
          end
          def close
            p "JERE"
            @zipfile.commit if @zipfile.commit_required?
          end
        end
      end
      class File < DelegateClass(::Zip::ZipFileSystem::ZipFsFile)
        def open(filename, openMode, *args)
          zipstream = super
          
          case openMode
          when 'r' then Stream::Input.new(super)
          when 'w' then Stream::Output.new(super)
          end
        end
      end
      class Dir < DelegateClass(::Zip::ZipFileSystem::ZipFsDir)
        def open(*args)
          super
        end
      end
      class RootDir < DelegateClass(::Zip::ZipFile)
        
      end
    end
  end
end
__END__



    class CentralDir
      include Enumerable

      def initialize(zipfilepath)
        @zipfilepath = zipfilepath
        @zipfile = Zip::ZipFile.new(@zipfilepath)
        #puts @zipfile.methods.sort
        topents = {}
        @zipfile.entries.map{ |ent|
          top = ent.to_s.match(%r|^(/?[^/]+(/)?)|)[1]
          topents[top] = ent if top == ent.to_s
        }
        fs = RIO::ZipFile::FS::InFile.new(@zipfile)
        @topents = topents.values.map{ |v| rio(RIO::Path::RL.new(v.to_s,{:fs => fs})) }
        @entidx = 0
      end
#      def method_missing(sym,*args,&block)
#        @zipfile.__send__(sym,*args,&block)
#      end
      def read
        return nil if @entidx >= @topents.size
        @entidx += 1
        @topents[@entidx-1]
      end
      def rewind
        @entidx = 0
      end
      def each(&block)
        @topents.each { |ent|
          yield ent
        }
      end
      def close
      end
    end
    module FS
      class Base < RIO::FS::Base
      end
      class InFile < Base
        attr_reader :file,:dir
        def initialize(zipfile)
          @zipfile = zipfile
          @file = @zipfile.file
          @dir = @zipfile.dir
          @test = @zipfile.file
        end
        include RIO::FS::File
        include RIO::FS::Dir
        include RIO::FS::Test
        include RIO::FS::Str
      end
      
      class CentralDir < RIO::FS::Native
        def initialize(zipfilepath)
          @zipfilepath = zipfilepath
          @zipfile = Zip::ZipFile.new(@zipfilepath)
          super
        end
        def mkdir(path)
          @zipfile.mkdir(path)
        end
        def rmdir(path)
          @zipfile.remove(path)
        end
        def file()
          self
        end
        def open(zipfilepath)
          @zipfilepath = zipfilepath
          @zipfile = Zip::ZipFile.new(@zipfilepath)
          RIO::ZipFile::CentralDir.new(@zipfile)
        end

      end

    end
  end
end