// Copyright (c) 2016 VMware, Inc. All Rights Reserved.
//
// This product is licensed to you under the Apache License, Version 2.0 (the "License").
// You may not use this product except in compliance with the License.
//
// This product may include a number of subcomponents with separate copyright notices and
// license terms. Your use of these subcomponents is subject to the terms and conditions
// of the subcomponent's license, as noted in the LICENSE file.

package photon

import (
	"bytes"
	"crypto/rand"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

type restClient struct {
	httpClient                *http.Client
	logger                    *log.Logger
	Auth                      *AuthAPI
	UpdateAccessTokenCallback TokenCallback
}

type request struct {
	Method      string
	URL         string
	ContentType string
	Body        io.Reader
	Tokens      *TokenOptions
}

type page struct {
	Items            []interface{} `json:"items"`
	NextPageLink     string        `json:"nextPageLink"`
	PreviousPageLink string        `json:"previousPageLink"`
}

type documentList struct {
	Items []interface{}
}

type bodyRewinder func() io.Reader

const appJson string = "application/json"

// Root URL specifies the API version.
const rootUrl string = "/v1"

// From https://golang.org/src/mime/multipart/writer.go
var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")

func (client *restClient) AppendSlice(origSlice []interface{}, dataToAppend []interface{}) []interface{} {
	origLen := len(origSlice)
	newLen := origLen + len(dataToAppend)

	if newLen > cap(origSlice) {
		newSlice := make([]interface{}, (newLen+1)*2)
		copy(newSlice, origSlice)
		origSlice = newSlice
	}

	origSlice = origSlice[0:newLen]
	copy(origSlice[origLen:newLen], dataToAppend)

	return origSlice
}

func (client *restClient) Get(url string, tokens *TokenOptions) (res *http.Response, err error) {
	req := request{"GET", url, "", nil, tokens}
	res, err = client.SendRequest(&req, nil)
	return
}

func (client *restClient) GetList(endpoint string, url string, tokens *TokenOptions) (result []byte, err error) {
	req := request{"GET", url, "", nil, tokens}
	res, err := client.SendRequest(&req, nil)
	if err != nil {
		return
	}
	res, err = getError(res)
	if err != nil {
		return
	}

	decoder := json.NewDecoder(res.Body)
	decoder.UseNumber()

	page := &page{}
	err = decoder.Decode(page)
	if err != nil {
		return
	}

	documentList := &documentList{}
	documentList.Items = client.AppendSlice(documentList.Items, page.Items)

	for page.NextPageLink != "" {
		req = request{"GET", endpoint + page.NextPageLink, "", nil, tokens}
		res, err = client.SendRequest(&req, nil)
		if err != nil {
			return
		}
		res, err = getError(res)
		if err != nil {
			return
		}

		decoder = json.NewDecoder(res.Body)
		decoder.UseNumber()

		page.NextPageLink = ""
		page.PreviousPageLink = ""

		err = decoder.Decode(page)
		if err != nil {
			return
		}

		documentList.Items = client.AppendSlice(documentList.Items, page.Items)
	}

	result, err = json.Marshal(documentList)

	return
}

func (client *restClient) Post(url string, contentType string, body io.ReadSeeker, tokens *TokenOptions) (res *http.Response, err error) {
	res, err = client.SendRequestCommon("POST", url, contentType, body, tokens)
	return
}

func (client *restClient) Patch(url string, contentType string, body io.ReadSeeker, tokens *TokenOptions) (res *http.Response, err error) {
	res, err = client.SendRequestCommon("PATCH", url, contentType, body, tokens)
	return
}

func (client *restClient) Put(url string, contentType string, body io.ReadSeeker, tokens *TokenOptions) (res *http.Response, err error) {
	res, err = client.SendRequestCommon("PUT", url, contentType, body, tokens)
	return
}

func (client *restClient) Delete(url string, tokens *TokenOptions) (res *http.Response, err error) {
	req := request{"DELETE", url, "", nil, tokens}
	res, err = client.SendRequest(&req, nil)
	return
}

func (client *restClient) SendRequestCommon(method string, url string, contentType string, body io.ReadSeeker, tokens *TokenOptions) (res *http.Response, err error) {
	if contentType == "" {
		contentType = appJson
	}

	req := request{method, url, contentType, body, tokens}
	rewinder := func() io.Reader {
		body.Seek(0, 0)
		return body
	}
	res, err = client.SendRequest(&req, rewinder)
	return
}

func (client *restClient) SendRequest(req *request, bodyRewinder bodyRewinder) (res *http.Response, err error) {
	res, err = client.sendRequestHelper(req)
	// In most cases, we'll return immediately
	// If the operation succeeded, but we got a 401 response and if we're using
	// authentication, then we'll look into the body to see if the token expired
	if err != nil {
		return res, err
	}
	if res.StatusCode != 401 {
		// It's not a 401, so the token didn't expire
		return res, err
	}
	if req.Tokens == nil || req.Tokens.AccessToken == "" {
		// We don't have a token, so we can't renew the token, no need to proceed
		return res, err
	}

	// We're going to look in the body to see if it failed because the token expired
	// This means we need to read the body, but the functions that call us also
	// expect to read the body. So we read the body, then create a new reader
	// so they can read the body as normal.
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return res, err
	}
	res.Body = ioutil.NopCloser(bytes.NewReader(body))

	// Now see if we had an expired token or not
	var apiError ApiError
	err = json.Unmarshal(body, &apiError)
	if err != nil {
		return res, err
	}
	if apiError.Code != "ExpiredAuthToken" {
		return res, nil
	}

	// We were told that the access token expired, so try to renew it.
	// Note that this looks recursive because GetTokensByRefreshToken() will
	// call the /auth API, and therefore SendRequest(). However, it calls
	// without a token, so we avoid having a loop
	newTokens, err := client.Auth.GetTokensByRefreshToken(req.Tokens.RefreshToken)
	if err != nil {
		return res, err
	}
	req.Tokens.AccessToken = newTokens.AccessToken
	if client.UpdateAccessTokenCallback != nil {
		client.UpdateAccessTokenCallback(newTokens.AccessToken)
	}
	if req.Body != nil && bodyRewinder != nil {
		req.Body = bodyRewinder()
	}
	res, err = client.sendRequestHelper(req)
	return res, nil
}

func (client *restClient) sendRequestHelper(req *request) (res *http.Response, err error) {
	r, err := http.NewRequest(req.Method, req.URL, req.Body)
	if err != nil {
		client.logger.Printf("An error occured creating request %s on %s. Error: %s", req.Method, req.URL, err)
		return
	}
	if req.ContentType != "" {
		r.Header.Add("Content-Type", req.ContentType)
	}
	if req.Tokens != nil && req.Tokens.AccessToken != "" {
		r.Header.Add("Authorization", "Bearer "+req.Tokens.AccessToken)
	}
	res, err = client.httpClient.Do(r)
	if err != nil {
		client.logger.Printf("An error occured when calling %s on %s. Error: %s", req.Method, req.URL, err)
		return
	}

	client.logger.Printf("[%s] %s - %s %s", res.Header.Get("request-id"), res.Status, req.Method, req.URL)
	return
}

func (client *restClient) MultipartUploadFile(url, filePath string, params map[string]string, tokens *TokenOptions) (res *http.Response, err error) {
	file, err := os.Open(filePath)
	if err != nil {
		return
	}
	defer file.Close()
	return client.MultipartUpload(url, file, filepath.Base(filePath), params, tokens)
}

func (client *restClient) MultipartUpload(url string, reader io.ReadSeeker, filename string, params map[string]string, tokens *TokenOptions) (res *http.Response, err error) {
	boundary := client.randomBoundary()
	multiReader, contentType := client.createMultiReader(reader, filename, params, boundary)
	rewinder := func() io.Reader {
		reader.Seek(0, 0)
		multiReader, _ := client.createMultiReader(reader, filename, params, boundary)
		return multiReader
	}
	res, err = client.SendRequest(&request{"POST", url, contentType, multiReader, tokens}, rewinder)

	return
}

func (client *restClient) createMultiReader(reader io.ReadSeeker, filename string, params map[string]string, boundary string) (io.Reader, string) {
	// The mime/multipart package does not support streaming multipart data from disk,
	// at least not without complicated, problematic goroutines that simultaneously read/write into a buffer.
	// A much easier approach is to just construct the multipart request by hand, using io.MultiPart to
	// concatenate the parts of the request together into a single io.Reader.
	parts := []io.Reader{}

	// Create a part for each key, val pair in params
	for k, v := range params {
		parts = append(parts, client.createFieldPart(k, v, boundary))
	}

	start := fmt.Sprintf("\r\n--%s\r\n", boundary)
	start += fmt.Sprintf("Content-Disposition: form-data; name=\"file\"; filename=\"%s\"\r\n", quoteEscaper.Replace(filename))
	start += fmt.Sprintf("Content-Type: application/octet-stream\r\n\r\n")
	end := fmt.Sprintf("\r\n--%s--", boundary)

	// The request will consist of a reader to begin the request, a reader which points
	// to the file data on disk, and a reader containing the closing boundary of the request.
	parts = append(parts, strings.NewReader(start), reader, strings.NewReader(end))

	contentType := fmt.Sprintf("multipart/form-data; boundary=%s", boundary)

	return io.MultiReader(parts...), contentType
}

// From https://golang.org/src/mime/multipart/writer.go
func (client *restClient) randomBoundary() string {
	var buf [30]byte
	_, err := io.ReadFull(rand.Reader, buf[:])
	if err != nil {
		panic(err)
	}
	return fmt.Sprintf("%x", buf[:])
}

// Creates a reader that encapsulates a single multipart form part
func (client *restClient) createFieldPart(fieldname, value, boundary string) io.Reader {
	str := fmt.Sprintf("\r\n--%s\r\n", boundary)
	str += fmt.Sprintf("Content-Disposition: form-data; name=\"%s\"\r\n\r\n", quoteEscaper.Replace(fieldname))
	str += value
	return strings.NewReader(str)
}
