func (p PostPolicy) marshalJSON() []byte {
	expirationStr := `"expiration":"` + p.expiration.Format(expirationDateFormat) + `"`
	var conditionsStr string
	conditions := []string{}
	for _, po := range p.conditions {
		conditions = append(conditions, fmt.Sprintf("[\"%s\",\"%s\",\"%s\"]", po.matchType, po.condition, po.value))
	}
	if p.contentLengthRange.min != 0 || p.contentLengthRange.max != 0 {
		conditions = append(conditions, fmt.Sprintf("[\"content-length-range\", %d, %d]",
			p.contentLengthRange.min, p.contentLengthRange.max))
	}
	if len(conditions) > 0 {
		conditionsStr = `"conditions":[` + strings.Join(conditions, ",") + "]"
	}
	retStr := "{"
	retStr = retStr + expirationStr + ","
	retStr = retStr + conditionsStr
	retStr = retStr + "}"
	return []byte(retStr)
}
marshalJSON - Provides Marshaled JSON in bytes.
package minio
import (
	"encoding/base64"
	"fmt"
	"strings"
	"time"
)
const expirationDateFormat = "2006-01-02T15:04:05.999Z"
type policyCondition struct {
	matchType string
	condition string
	value     string
}
type PostPolicy struct {
	expiration time.Time
	conditions []policyCondition
	contentLengthRange struct {
		min int64
		max int64
	}
	formData map[string]string
}
func NewPostPolicy() *PostPolicy {
	p := &PostPolicy{}
	p.conditions = make([]policyCondition, 0)
	p.formData = make(map[string]string)
	return p
}
func (p *PostPolicy) SetExpires(t time.Time) error {
	if t.IsZero() {
		return ErrInvalidArgument("No expiry time set.")
	}
	p.expiration = t
	return nil
}
func (p *PostPolicy) SetKey(key string) error {
	if strings.TrimSpace(key) == "" || key == "" {
		return ErrInvalidArgument("Object name is empty.")
	}
	policyCond := policyCondition{
		matchType: "eq",
		condition: "$key",
		value:     key,
	}
	if err := p.addNewPolicy(policyCond); err != nil {
		return err
	}
	p.formData["key"] = key
	return nil
}
func (p *PostPolicy) SetKeyStartsWith(keyStartsWith string) error {
	if strings.TrimSpace(keyStartsWith) == "" || keyStartsWith == "" {
		return ErrInvalidArgument("Object prefix is empty.")
	}
	policyCond := policyCondition{
		matchType: "starts-with",
		condition: "$key",
		value:     keyStartsWith,
	}
	if err := p.addNewPolicy(policyCond); err != nil {
		return err
	}
	p.formData["key"] = keyStartsWith
	return nil
}
func (p *PostPolicy) SetBucket(bucketName string) error {
	if strings.TrimSpace(bucketName) == "" || bucketName == "" {
		return ErrInvalidArgument("Bucket name is empty.")
	}
	policyCond := policyCondition{
		matchType: "eq",
		condition: "$bucket",
		value:     bucketName,
	}
	if err := p.addNewPolicy(policyCond); err != nil {
		return err
	}
	p.formData["bucket"] = bucketName
	return nil
}
func (p *PostPolicy) SetCondition(matchType, condition, value string) error {
	if strings.TrimSpace(value) == "" || value == "" {
		return ErrInvalidArgument("No value specified for condition")
	}
	policyCond := policyCondition{
		matchType: matchType,
		condition: "$" + condition,
		value:     value,
	}
	if condition == "X-Amz-Credential" || condition == "X-Amz-Date" || condition == "X-Amz-Algorithm" {
		if err := p.addNewPolicy(policyCond); err != nil {
			return err
		}
		p.formData[condition] = value
		return nil
	}
	return ErrInvalidArgument("Invalid condition in policy")
}
func (p *PostPolicy) SetContentType(contentType string) error {
	if strings.TrimSpace(contentType) == "" || contentType == "" {
		return ErrInvalidArgument("No content type specified.")
	}
	policyCond := policyCondition{
		matchType: "eq",
		condition: "$Content-Type",
		value:     contentType,
	}
	if err := p.addNewPolicy(policyCond); err != nil {
		return err
	}
	p.formData["Content-Type"] = contentType
	return nil
}
func (p *PostPolicy) SetContentLengthRange(min, max int64) error {
	if min > max {
		return ErrInvalidArgument("Minimum limit is larger than maximum limit.")
	}
	if min < 0 {
		return ErrInvalidArgument("Minimum limit cannot be negative.")
	}
	if max < 0 {
		return ErrInvalidArgument("Maximum limit cannot be negative.")
	}
	p.contentLengthRange.min = min
	p.contentLengthRange.max = max
	return nil
}
func (p *PostPolicy) SetSuccessStatusAction(status string) error {
	if strings.TrimSpace(status) == "" || status == "" {
		return ErrInvalidArgument("Status is empty")
	}
	policyCond := policyCondition{
		matchType: "eq",
		condition: "$success_action_status",
		value:     status,
	}
	if err := p.addNewPolicy(policyCond); err != nil {
		return err
	}
	p.formData["success_action_status"] = status
	return nil
}
func (p *PostPolicy) SetUserMetadata(key string, value string) error {
	if strings.TrimSpace(key) == "" || key == "" {
		return ErrInvalidArgument("Key is empty")
	}
	if strings.TrimSpace(value) == "" || value == "" {
		return ErrInvalidArgument("Value is empty")
	}
	headerName := fmt.Sprintf("x-amz-meta-%s", key)
	policyCond := policyCondition{
		matchType: "eq",
		condition: fmt.Sprintf("$%s", headerName),
		value:     value,
	}
	if err := p.addNewPolicy(policyCond); err != nil {
		return err
	}
	p.formData[headerName] = value
	return nil
}
func (p *PostPolicy) SetUserData(key string, value string) error {
	if key == "" {
		return ErrInvalidArgument("Key is empty")
	}
	if value == "" {
		return ErrInvalidArgument("Value is empty")
	}
	headerName := fmt.Sprintf("x-amz-%s", key)
	policyCond := policyCondition{
		matchType: "eq",
		condition: fmt.Sprintf("$%s", headerName),
		value:     value,
	}
	if err := p.addNewPolicy(policyCond); err != nil {
		return err
	}
	p.formData[headerName] = value
	return nil
}
func (p *PostPolicy) addNewPolicy(policyCond policyCondition) error {
	if policyCond.matchType == "" || policyCond.condition == "" || policyCond.value == "" {
		return ErrInvalidArgument("Policy fields are empty.")
	}
	p.conditions = append(p.conditions, policyCond)
	return nil
}
func (p PostPolicy) String() string {
	return string(p.marshalJSON())
}