// 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 are considered relative to
//   the root specified with NewHttpZipFS (even if the paths start with a '/').

// 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 {
	path          string // absolute path within zip FS without leading '/'
	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) {
	var list []os.FileInfo
	dirname := f.path + "/"
	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) 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(name string) (http.File, os.Error) {
	// fs.root does not start with '/'.
	path := path.Join(fs.root, name) // path is clean
	index, exact := fs.list.lookup(path)
	if index < 0 || !strings.HasPrefix(path, fs.root) {
		// file not found or not under root
		return nil, fmt.Errorf("file not found: %s", name)
	}

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

	// not an exact match - must be a directory
	return &httpZipFile{
		path,
		os.FileInfo{
			Name: name,
			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()
}

// NewHttpZipFS creates a new http.FileSystem based on the contents of
// the zip file rc restricted to the directory tree specified by root;
// root must be an absolute path.
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)}
}
