// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file provides an implementation of the http.FileSystem
// interface based on the contents of a .zip file.
//
// Assumptions:
//
// - The file paths stored in the zip file must use a slash ('/') as path
//   separator; and they must be relative (i.e., they must not start with
//   a '/' - this is usually the case if the file was created w/o special
//   options).
// - The zip file system treats the file paths found in the zip internally
//   like absolute paths w/o a leading '/'; i.e., the paths are considered
//   relative to the root of the file system.
// - All path arguments to file system methods must be absolute paths.

// TODO(gri) Should define a commonly used FileSystem API that is the same
//           for http and godoc. Then we only need one zip-file based file
//           system implementation.

package main

import (
	"archive/zip"
	"fmt"
	"http"
	"io"
	"os"
	"path"
	"sort"
	"strings"
)

// We cannot import syscall on app engine.
// TODO(gri) Once we have a truly abstract FileInfo implementation
//           this won't be needed anymore.
const (
	S_IFDIR = 0x4000 // == syscall.S_IFDIR
	S_IFREG = 0x8000 // == syscall.S_IFREG
)

// httpZipFile is the zip-file based implementation of http.File
type httpZipFile struct {
	info          os.FileInfo
	io.ReadCloser // nil for directory
	list          zipList
}

func (f *httpZipFile) Close() os.Error {
	if f.info.IsRegular() {
		return f.ReadCloser.Close()
	}
	f.list = nil
	return nil
}

func (f *httpZipFile) Stat() (*os.FileInfo, os.Error) {
	return &f.info, nil
}

func (f *httpZipFile) Readdir(count int) ([]os.FileInfo, os.Error) {
	println("Readdir", f.info.Name)
	if f.info.IsRegular() {
		return nil, fmt.Errorf("Readdir called for regular file: %s", f.info.Name)
	}

	var list []os.FileInfo
	dirname := zipPath(f.info.Name) + "/"
	prevname := ""
	for i, e := range f.list {
		if count == 0 {
			f.list = f.list[i:]
			break
		}
		if !strings.HasPrefix(e.Name, dirname) {
			f.list = nil
			break // not in the same directory anymore
		}
		name := e.Name[len(dirname):] // local name
		var mode uint32
		var size, mtime_ns int64
		if i := strings.IndexRune(name, '/'); i >= 0 {
			// We infer directories from files in subdirectories.
			// If we have x/y, return a directory entry for x.
			name = name[0:i] // keep local directory name only
			mode = S_IFDIR
			// no size or mtime_ns for directories
		} else {
			mode = S_IFREG
			size = int64(e.UncompressedSize)
			mtime_ns = e.Mtime_ns()
		}
		// If we have x/y and x/z, don't return two directory entries for x.
		// TODO(gri): It should be possible to do this more efficiently
		// by determining the (fs.list) range of local directory entries
		// (via two binary searches).
		if name != prevname {
			list = append(list, os.FileInfo{
				Name:     name,
				Mode:     mode,
				Size:     size,
				Mtime_ns: mtime_ns,
			})
			prevname = name
			count--
		}
	}

	if count >= 0 && len(list) == 0 {
		return nil, os.EOF
	}

	return list, nil
}

func (f *httpZipFile) Read(buf []byte) (int, os.Error) {
	if f.info.IsRegular() {
		return f.ReadCloser.Read(buf)
	}
	return 0, fmt.Errorf("Read called for directory: %s", f.info.Name)
}

func (f *httpZipFile) Seek(offset int64, whence int) (int64, os.Error) {
	return 0, fmt.Errorf("Seek not implemented for zip file entry: %s", f.info.Name)
}

// httpZipFS is the zip-file based implementation of http.FileSystem
type httpZipFS struct {
	*zip.ReadCloser
	list zipList
	root string
}

func (fs *httpZipFS) Open(abspath string) (http.File, os.Error) {
	name := path.Join(fs.root, abspath)
	index := fs.list.lookup(name)
	if index < 0 {
		return nil, fmt.Errorf("file not found: %s", abspath)
	}

	if f := fs.list[index]; f.Name == name {
		// exact match found - must be a file
		rc, err := f.Open()
		if err != nil {
			return nil, err
		}
		return &httpZipFile{
			os.FileInfo{
				Name:     abspath,
				Mode:     S_IFREG,
				Size:     int64(f.UncompressedSize),
				Mtime_ns: f.Mtime_ns(),
			},
			rc,
			nil,
		}, nil
	}

	// not an exact match - must be a directory
	println("opened directory", abspath, len(fs.list[index:]))
	return &httpZipFile{
		os.FileInfo{
			Name: abspath,
			Mode: S_IFDIR,
			// no size or mtime_ns for directories
		},
		nil,
		fs.list[index:],
	}, nil
}

func (fs *httpZipFS) Close() os.Error {
	fs.list = nil
	return fs.ReadCloser.Close()
}

func NewHttpZipFS(rc *zip.ReadCloser, root string) http.FileSystem {
	list := make(zipList, len(rc.File))
	copy(list, rc.File) // sort a copy of rc.File
	sort.Sort(list)
	return &httpZipFS{rc, list, zipPath(root)}
}
