package controllers

import (
	"fmt"
	"github.com/gogf/gf/net/ghttp"
	"gxt-file-server/app/bll"
	context2 "gxt-file-server/app/context"
	"gxt-file-server/app/errors"
	"gxt-file-server/app/schema"
	"gxt-file-server/pkg/gplus"
	"net/url"
	"strconv"
	"strings"
)

// NewFile 创建文件管理控制器
func NewFile(bFile bll.IFile) *File {
	return &File{
		FileBll: bFile,
	}
}

// File 文件管理
// @Name File
// @Description 文件管理
type File struct {
	FileBll bll.IFile
}

// Upload 上传文件
func (a *File) Upload(r *ghttp.Request) {
	var params schema.UploadParams
	if err := gplus.ParseJson(r, &params); err != nil {
		gplus.ResError(r, err)
	}
	ctx := gplus.NewContext(r)
	if v := r.Header.Get("FILE-EXPIRE"); v != "" {
		m, err := strconv.Atoi(v)
		if err != nil {
			gplus.ResError(r, errors.ErrHeaderParamsError)
		}
		ctx = context2.NewFileExpireContext(ctx, m)
	}
	if v := r.Header.Get("FILE-HASH"); v != "" {
		ctx = context2.NewFileHashContext(ctx, v)
	}
	info, err := a.FileBll.Upload(ctx, r.Request, params.FormKey, params.BaseUrl)
	if err != nil {
		gplus.ResError(r, err)
		return
	}

	gplus.ResSuccess(r, info)
}

// Download 下载文件
func (a *File) Download(r *ghttp.Request) {
	if r.GetString("path") == "" || r.GetString("name") == "" {
		gplus.ResError(r, errors.ErrBadRequest)
	}
	path, err := url.PathUnescape(r.GetString("path"))
	if err != nil {
		gplus.ResError(r, err)
	}
	fileData, contentType, err := a.FileBll.Download(gplus.NewContext(r), path)
	if err != nil {
		gplus.ResError(r, err)
	}
	if strings.HasPrefix(contentType, "text/html") ||
		strings.HasPrefix(contentType, "application/javascript") {
		contentType = "text/plain; charset=utf-8"
	}
	r.Response.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", r.GetString("name")))
	r.Response.Header().Set("Content-Type", "application/octet-stream")
	// r.Response.Header().Set("Content-Type", contentType)
	r.Response.Header().Set("Cache-Control", "max-age=31536000")
	r.Response.Header().Set("Content-Length", strconv.FormatInt(int64(len(fileData)), 10))
	r.Response.Write(fileData)
}

// Persistent 设置文件为持久化
func (a *File) Persistent(r *ghttp.Request) {
	var param schema.PersistentFileRequest
	if err := gplus.ParseJson(r, &param); err != nil {
		gplus.ResError(r, err)
	}
	err := a.FileBll.Persistent(gplus.NewContext(r), param.Hash)
	if err != nil {
		gplus.ResError(r, err)
	}
	gplus.ResOK(r)
}

// Chunk 分块上传
func (a *File) Chunk(r *ghttp.Request) {
	var param schema.FileChunkUploadReq
	if err := gplus.ParseJson(r, &param); err != nil {
		gplus.ResError(r, err)
	}
	result, err := a.FileBll.ChunkUpload(gplus.NewContext(r), schema.FileChunkParams{
		HttpRequest: r.Request,
		FormKey:     param.FormKey,
		BaseUrl:     param.BaseUrl,
		Index:       param.Index,
		Total:       param.Total,
		Hash:        param.Hash,
	})
	if err != nil {
		gplus.ResError(r, err)
	}
	gplus.ResSuccess(r, result)
}

// Merge 文件分块合并
func (a *File) Merge(r *ghttp.Request) {
	var param schema.FileMergeParams
	if err := gplus.ParseJson(r, &param); err != nil {
		gplus.ResError(r, err)
	}
	result, err := a.FileBll.FileMerge(gplus.NewContext(r), schema.FileMergeParams{
		HttpRequest: r.Request,
		BaseUrl:     param.BaseUrl,
		Total:       param.Total,
		Hash:        param.Hash,
		FileName:    param.FileName,
	})
	if err != nil {
		gplus.ResError(r, err)
	}
	gplus.ResSuccess(r, result)
}
