package storage

// Copyright 2017 Microsoft Corporation
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"sync"
)

const fourMB = uint64(4194304)
const oneTB = uint64(1099511627776)

// Export maximum range and file sizes
const MaxRangeSize = fourMB
const MaxFileSize = oneTB

// File represents a file on a share.
type File struct {
	fsc                *FileServiceClient
	Metadata           map[string]string
	Name               string `xml:"Name"`
	parent             *Directory
	Properties         FileProperties `xml:"Properties"`
	share              *Share
	FileCopyProperties FileCopyState
	mutex              *sync.Mutex
}

// FileProperties contains various properties of a file.
type FileProperties struct {
	CacheControl string `header:"x-ms-cache-control"`
	Disposition  string `header:"x-ms-content-disposition"`
	Encoding     string `header:"x-ms-content-encoding"`
	Etag         string
	Language     string `header:"x-ms-content-language"`
	LastModified string
	Length       uint64 `xml:"Content-Length" header:"x-ms-content-length"`
	MD5          string `header:"x-ms-content-md5"`
	Type         string `header:"x-ms-content-type"`
}

// FileCopyState contains various properties of a file copy operation.
type FileCopyState struct {
	CompletionTime string
	ID             string `header:"x-ms-copy-id"`
	Progress       string
	Source         string
	Status         string `header:"x-ms-copy-status"`
	StatusDesc     string
}

// FileStream contains file data returned from a call to GetFile.
type FileStream struct {
	Body       io.ReadCloser
	ContentMD5 string
}

// FileRequestOptions will be passed to misc file operations.
// Currently just Timeout (in seconds) but could expand.
type FileRequestOptions struct {
	Timeout uint // timeout duration in seconds.
}

func prepareOptions(options *FileRequestOptions) url.Values {
	params := url.Values{}
	if options != nil {
		params = addTimeout(params, options.Timeout)
	}
	return params
}

// FileRanges contains a list of file range information for a file.
//
// See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/List-Ranges
type FileRanges struct {
	ContentLength uint64
	LastModified  string
	ETag          string
	FileRanges    []FileRange `xml:"Range"`
}

// FileRange contains range information for a file.
//
// See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/List-Ranges
type FileRange struct {
	Start uint64 `xml:"Start"`
	End   uint64 `xml:"End"`
}

func (fr FileRange) String() string {
	return fmt.Sprintf("bytes=%d-%d", fr.Start, fr.End)
}

// builds the complete file path for this file object
func (f *File) buildPath() string {
	return f.parent.buildPath() + "/" + f.Name
}

// ClearRange releases the specified range of space in a file.
//
// See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Put-Range
func (f *File) ClearRange(fileRange FileRange, options *FileRequestOptions) error {
	var timeout *uint
	if options != nil {
		timeout = &options.Timeout
	}
	headers, err := f.modifyRange(nil, fileRange, timeout, nil)
	if err != nil {
		return err
	}

	f.updateEtagAndLastModified(headers)
	return nil
}

// Create creates a new file or replaces an existing one.
//
// See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Create-File
func (f *File) Create(maxSize uint64, options *FileRequestOptions) error {
	if maxSize > oneTB {
		return fmt.Errorf("max file size is 1TB")
	}
	params := prepareOptions(options)
	headers := headersFromStruct(f.Properties)
	headers["x-ms-content-length"] = strconv.FormatUint(maxSize, 10)
	headers["x-ms-type"] = "file"

	outputHeaders, err := f.fsc.createResource(f.buildPath(), resourceFile, params, mergeMDIntoExtraHeaders(f.Metadata, headers), []int{http.StatusCreated})
	if err != nil {
		return err
	}

	f.Properties.Length = maxSize
	f.updateEtagAndLastModified(outputHeaders)
	return nil
}

// CopyFile operation copied a file/blob from the sourceURL to the path provided.
//
// See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/copy-file
func (f *File) CopyFile(sourceURL string, options *FileRequestOptions) error {
	extraHeaders := map[string]string{
		"x-ms-type":        "file",
		"x-ms-copy-source": sourceURL,
	}
	params := prepareOptions(options)

	headers, err := f.fsc.createResource(f.buildPath(), resourceFile, params, mergeMDIntoExtraHeaders(f.Metadata, extraHeaders), []int{http.StatusAccepted})
	if err != nil {
		return err
	}

	f.updateEtagAndLastModified(headers)
	f.FileCopyProperties.ID = headers.Get("X-Ms-Copy-Id")
	f.FileCopyProperties.Status = headers.Get("X-Ms-Copy-Status")
	return nil
}

// Delete immediately removes this file from the storage account.
//
// See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Delete-File2
func (f *File) Delete(options *FileRequestOptions) error {
	return f.fsc.deleteResource(f.buildPath(), resourceFile, options)
}

// DeleteIfExists removes this file if it exists.
//
// See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Delete-File2
func (f *File) DeleteIfExists(options *FileRequestOptions) (bool, error) {
	resp, err := f.fsc.deleteResourceNoClose(f.buildPath(), resourceFile, options)
	if resp != nil {
		defer drainRespBody(resp)
		if resp.StatusCode == http.StatusAccepted || resp.StatusCode == http.StatusNotFound {
			return resp.StatusCode == http.StatusAccepted, nil
		}
	}
	return false, err
}

// GetFileOptions includes options for a get file operation
type GetFileOptions struct {
	Timeout       uint
	GetContentMD5 bool
}

// DownloadToStream operation downloads the file.
//
// See: https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/get-file
func (f *File) DownloadToStream(options *FileRequestOptions) (io.ReadCloser, error) {
	params := prepareOptions(options)
	resp, err := f.fsc.getResourceNoClose(f.buildPath(), compNone, resourceFile, params, http.MethodGet, nil)
	if err != nil {
		return nil, err
	}

	if err = checkRespCode(resp, []int{http.StatusOK}); err != nil {
		drainRespBody(resp)
		return nil, err
	}
	return resp.Body, nil
}

// DownloadRangeToStream operation downloads the specified range of this file with optional MD5 hash.
//
// See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/get-file
func (f *File) DownloadRangeToStream(fileRange FileRange, options *GetFileOptions) (fs FileStream, err error) {
	extraHeaders := map[string]string{
		"Range": fileRange.String(),
	}
	params := url.Values{}
	if options != nil {
		if options.GetContentMD5 {
			if isRangeTooBig(fileRange) {
				return fs, fmt.Errorf("must specify a range less than or equal to 4MB when getContentMD5 is true")
			}
			extraHeaders["x-ms-range-get-content-md5"] = "true"
		}
		params = addTimeout(params, options.Timeout)
	}

	resp, err := f.fsc.getResourceNoClose(f.buildPath(), compNone, resourceFile, params, http.MethodGet, extraHeaders)
	if err != nil {
		return fs, err
	}

	if err = checkRespCode(resp, []int{http.StatusOK, http.StatusPartialContent}); err != nil {
		drainRespBody(resp)
		return fs, err
	}

	fs.Body = resp.Body
	if options != nil && options.GetContentMD5 {
		fs.ContentMD5 = resp.Header.Get("Content-MD5")
	}
	return fs, nil
}

// Exists returns true if this file exists.
func (f *File) Exists() (bool, error) {
	exists, headers, err := f.fsc.resourceExists(f.buildPath(), resourceFile)
	if exists {
		f.updateEtagAndLastModified(headers)
		f.updateProperties(headers)
	}
	return exists, err
}

// FetchAttributes updates metadata and properties for this file.
// See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/get-file-properties
func (f *File) FetchAttributes(options *FileRequestOptions) error {
	params := prepareOptions(options)
	headers, err := f.fsc.getResourceHeaders(f.buildPath(), compNone, resourceFile, params, http.MethodHead)
	if err != nil {
		return err
	}

	f.updateEtagAndLastModified(headers)
	f.updateProperties(headers)
	f.Metadata = getMetadataFromHeaders(headers)
	return nil
}

// returns true if the range is larger than 4MB
func isRangeTooBig(fileRange FileRange) bool {
	if fileRange.End-fileRange.Start > fourMB {
		return true
	}

	return false
}

// ListRangesOptions includes options for a list file ranges operation
type ListRangesOptions struct {
	Timeout   uint
	ListRange *FileRange
}

// ListRanges returns the list of valid ranges for this file.
//
// See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/List-Ranges
func (f *File) ListRanges(options *ListRangesOptions) (*FileRanges, error) {
	params := url.Values{"comp": {"rangelist"}}

	// add optional range to list
	var headers map[string]string
	if options != nil {
		params = addTimeout(params, options.Timeout)
		if options.ListRange != nil {
			headers = make(map[string]string)
			headers["Range"] = options.ListRange.String()
		}
	}

	resp, err := f.fsc.listContent(f.buildPath(), params, headers)
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()
	var cl uint64
	cl, err = strconv.ParseUint(resp.Header.Get("x-ms-content-length"), 10, 64)
	if err != nil {
		ioutil.ReadAll(resp.Body)
		return nil, err
	}

	var out FileRanges
	out.ContentLength = cl
	out.ETag = resp.Header.Get("ETag")
	out.LastModified = resp.Header.Get("Last-Modified")

	err = xmlUnmarshal(resp.Body, &out)
	return &out, err
}

// modifies a range of bytes in this file
func (f *File) modifyRange(bytes io.Reader, fileRange FileRange, timeout *uint, contentMD5 *string) (http.Header, error) {
	if err := f.fsc.checkForStorageEmulator(); err != nil {
		return nil, err
	}
	if fileRange.End < fileRange.Start {
		return nil, errors.New("the value for rangeEnd must be greater than or equal to rangeStart")
	}
	if bytes != nil && isRangeTooBig(fileRange) {
		return nil, errors.New("range cannot exceed 4MB in size")
	}

	params := url.Values{"comp": {"range"}}
	if timeout != nil {
		params = addTimeout(params, *timeout)
	}

	uri := f.fsc.client.getEndpoint(fileServiceName, f.buildPath(), params)

	// default to clear
	write := "clear"
	cl := uint64(0)

	// if bytes is not nil then this is an update operation
	if bytes != nil {
		write = "update"
		cl = (fileRange.End - fileRange.Start) + 1
	}

	extraHeaders := map[string]string{
		"Content-Length": strconv.FormatUint(cl, 10),
		"Range":          fileRange.String(),
		"x-ms-write":     write,
	}

	if contentMD5 != nil {
		extraHeaders["Content-MD5"] = *contentMD5
	}

	headers := mergeHeaders(f.fsc.client.getStandardHeaders(), extraHeaders)
	resp, err := f.fsc.client.exec(http.MethodPut, uri, headers, bytes, f.fsc.auth)
	if err != nil {
		return nil, err
	}
	defer drainRespBody(resp)
	return resp.Header, checkRespCode(resp, []int{http.StatusCreated})
}

// SetMetadata replaces the metadata for this file.
//
// Some keys may be converted to Camel-Case before sending. All keys
// are returned in lower case by GetFileMetadata. HTTP header names
// are case-insensitive so case munging should not matter to other
// applications either.
//
// See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Set-File-Metadata
func (f *File) SetMetadata(options *FileRequestOptions) error {
	headers, err := f.fsc.setResourceHeaders(f.buildPath(), compMetadata, resourceFile, mergeMDIntoExtraHeaders(f.Metadata, nil), options)
	if err != nil {
		return err
	}

	f.updateEtagAndLastModified(headers)
	return nil
}

// SetProperties sets system properties on this file.
//
// Some keys may be converted to Camel-Case before sending. All keys
// are returned in lower case by SetFileProperties. HTTP header names
// are case-insensitive so case munging should not matter to other
// applications either.
//
// See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Set-File-Properties
func (f *File) SetProperties(options *FileRequestOptions) error {
	headers, err := f.fsc.setResourceHeaders(f.buildPath(), compProperties, resourceFile, headersFromStruct(f.Properties), options)
	if err != nil {
		return err
	}

	f.updateEtagAndLastModified(headers)
	return nil
}

// updates Etag and last modified date
func (f *File) updateEtagAndLastModified(headers http.Header) {
	f.Properties.Etag = headers.Get("Etag")
	f.Properties.LastModified = headers.Get("Last-Modified")
}

// updates file properties from the specified HTTP header
func (f *File) updateProperties(header http.Header) {
	size, err := strconv.ParseUint(header.Get("Content-Length"), 10, 64)
	if err == nil {
		f.Properties.Length = size
	}

	f.updateEtagAndLastModified(header)
	f.Properties.CacheControl = header.Get("Cache-Control")
	f.Properties.Disposition = header.Get("Content-Disposition")
	f.Properties.Encoding = header.Get("Content-Encoding")
	f.Properties.Language = header.Get("Content-Language")
	f.Properties.MD5 = header.Get("Content-MD5")
	f.Properties.Type = header.Get("Content-Type")
}

// URL gets the canonical URL to this file.
// This method does not create a publicly accessible URL if the file
// is private and this method does not check if the file exists.
func (f *File) URL() string {
	return f.fsc.client.getEndpoint(fileServiceName, f.buildPath(), nil)
}

// WriteRangeOptions includes options for a write file range operation
type WriteRangeOptions struct {
	Timeout    uint
	ContentMD5 string
}

// WriteRange writes a range of bytes to this file with an optional MD5 hash of the content (inside
// options parameter). Note that the length of bytes must match (rangeEnd - rangeStart) + 1 with
// a maximum size of 4MB.
//
// See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Put-Range
func (f *File) WriteRange(bytes io.Reader, fileRange FileRange, options *WriteRangeOptions) error {
	if bytes == nil {
		return errors.New("bytes cannot be nil")
	}
	var timeout *uint
	var md5 *string
	if options != nil {
		timeout = &options.Timeout
		md5 = &options.ContentMD5
	}

	headers, err := f.modifyRange(bytes, fileRange, timeout, md5)
	if err != nil {
		return err
	}
	// it's perfectly legal for multiple go routines to call WriteRange
	// on the same *File (e.g. concurrently writing non-overlapping ranges)
	// so we must take the file mutex before updating our properties.
	f.mutex.Lock()
	f.updateEtagAndLastModified(headers)
	f.mutex.Unlock()
	return nil
}
