package ctrl
import (
	"crypto/md5"
	"encoding/base32"
	. "github.com/mickael-kerjean/filestash/server/common"
	"io"
	"text/template"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)
var ETAGS SafeMapStringString = NewSafeMapStringString()
func StaticHandler(_path string) func(App, http.ResponseWriter, *http.Request) {
	return func(ctx App, res http.ResponseWriter, req *http.Request) {
		var srcPath string
		base := GetAbsolutePath(_path)
		if srcPath = JoinPath(base, req.URL.Path); srcPath == base {
			http.NotFound(res, req)
			return
		}
		ServeFile(res, req, srcPath)
	}
}
func IndexHandler(_path string) func(App, http.ResponseWriter, *http.Request) {
	return func(ctx App, res http.ResponseWriter, req *http.Request) {
		if req.URL.String() != URL_SETUP && Config.Get("auth.admin").String() == "" {
			http.Redirect(res, req, URL_SETUP, http.StatusTemporaryRedirect)
			return
		}
		srcPath := GetAbsolutePath(_path)
		ServeFile(res, req, srcPath)
	}
}
func AboutHandler(ctx App, res http.ResponseWriter, req *http.Request) {
	page := `
  
    
    
    
    
  
  
      {{index .App 0}} 
({{index .App 1}}) 
     {{range .Plugins}}
       {{ index . 0 }} ({{ index . 1 }}) 
{{end}}
     
  
`
	t, _ := template.New("about").Parse(page)
	t.Execute(res, struct {
		App     []string
		Plugins [][]string
	}{
		App:     []string{"Filestash " + APP_VERSION + "." + BUILD_NUMBER, hashFile(filepath.Join(GetCurrentDir(), "/filestash"), 6)},
		Plugins: func () [][]string {
			plugins := make([][]string, 0)
			pPath := filepath.Join(GetCurrentDir(), PLUGIN_PATH)
			if file, err := os.Open(pPath); err == nil {
				if files, err := file.Readdir(0); err == nil {
					for i:=0; i < len(files); i++ {
						plugins = append(plugins, []string{
							files[i].Name(),
							hashFile(pPath + "/" + files[i].Name(), 6),
						})
					}
				}
			}
			plugins = append(plugins, []string {
				"config.json",
				hashFile(filepath.Join(GetCurrentDir(), "/data/config/config.json"), 6),
			})
			return plugins
		}(),
	})
}
func hashFile (path string, n int) string {
	f, err := os.OpenFile(path, os.O_RDONLY, os.ModePerm)
	if err != nil {
		return ""
	}
	defer f.Close()
	h := md5.New()
	if _, err := io.Copy(h, f); err != nil {
		return ""
	}
	return base32.HexEncoding.EncodeToString(h.Sum(nil))[:n]
}
func ServeFile(res http.ResponseWriter, req *http.Request, filePath string) {
	zFilePath := filePath + ".gz"
	tags := ETAGS.Gets(filePath, zFilePath)
	etagNormal := tags[0]
	etagGzip := tags[1]
	
	if req.Header.Get("If-None-Match") != "" {
		browserTag := req.Header.Get("If-None-Match")
		if browserTag == etagNormal {
			res.WriteHeader(http.StatusNotModified)
			return
		} else if browserTag == etagGzip {
			res.WriteHeader(http.StatusNotModified)
			return
		}
	}
	head := res.Header()
	if strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") {
		if file, err := os.OpenFile(zFilePath, os.O_RDONLY, os.ModePerm); err == nil {
			head.Set("Content-Encoding", "gzip")
			if etagGzip == "" {
				tag := hashFile(zFilePath, 10)
				ETAGS.Set(zFilePath, tag)
				head.Set("Etag", tag)
			} else {
				head.Set("Etag", etagGzip)
			}
			io.Copy(res, file)
			return
		}
	}
	file, err := os.OpenFile(filePath, os.O_RDONLY, os.ModePerm)
	if err != nil {
		http.NotFound(res, req)
		return
	}
	if etagNormal == "" {
		tag := hashFile(filePath, 10)
		ETAGS.Set(filePath, tag)
		head.Set("Etag", tag)
	} else {
		head.Set("Etag", etagNormal)
	}
	io.Copy(res, file)
}