package restful

// Copyright 2015 Ernest Micklei. All rights reserved.
// Use of this source code is governed by a license
// that can be found in the LICENSE file.

import (
	"encoding/xml"
	"strings"
	"sync"
)

// EntityReaderWriter can read and write values using an encoding such as JSON,XML.
type EntityReaderWriter interface {
	// Read a serialized version of the value from the request.
	// The Request may have a decompressing reader. Depends on Content-Encoding.
	Read(req *Request, v interface{}) error

	// Write a serialized version of the value on the response.
	// The Response may have a compressing writer. Depends on Accept-Encoding.
	// status should be a valid Http Status code
	Write(resp *Response, status int, v interface{}) error
}

// entityAccessRegistry is a singleton
var entityAccessRegistry = &entityReaderWriters{
	protection: new(sync.RWMutex),
	accessors:  map[string]EntityReaderWriter{},
}

// entityReaderWriters associates MIME to an EntityReaderWriter
type entityReaderWriters struct {
	protection *sync.RWMutex
	accessors  map[string]EntityReaderWriter
}

func init() {
	RegisterEntityAccessor(MIME_JSON, NewEntityAccessorJSON(MIME_JSON))
	RegisterEntityAccessor(MIME_XML, NewEntityAccessorXML(MIME_XML))
}

// RegisterEntityAccessor add/overrides the ReaderWriter for encoding content with this MIME type.
func RegisterEntityAccessor(mime string, erw EntityReaderWriter) {
	entityAccessRegistry.protection.Lock()
	defer entityAccessRegistry.protection.Unlock()
	entityAccessRegistry.accessors[mime] = erw
}

// NewEntityAccessorJSON returns a new EntityReaderWriter for accessing JSON content.
// This package is already initialized with such an accessor using the MIME_JSON contentType.
func NewEntityAccessorJSON(contentType string) EntityReaderWriter {
	return entityJSONAccess{ContentType: contentType}
}

// NewEntityAccessorXML returns a new EntityReaderWriter for accessing XML content.
// This package is already initialized with such an accessor using the MIME_XML contentType.
func NewEntityAccessorXML(contentType string) EntityReaderWriter {
	return entityXMLAccess{ContentType: contentType}
}

// accessorAt returns the registered ReaderWriter for this MIME type.
func (r *entityReaderWriters) accessorAt(mime string) (EntityReaderWriter, bool) {
	r.protection.RLock()
	defer r.protection.RUnlock()
	er, ok := r.accessors[mime]
	if !ok {
		// retry with reverse lookup
		// more expensive but we are in an exceptional situation anyway
		for k, v := range r.accessors {
			if strings.Contains(mime, k) {
				return v, true
			}
		}
	}
	return er, ok
}

// entityXMLAccess is a EntityReaderWriter for XML encoding
type entityXMLAccess struct {
	// This is used for setting the Content-Type header when writing
	ContentType string
}

// Read unmarshalls the value from XML
func (e entityXMLAccess) Read(req *Request, v interface{}) error {
	return xml.NewDecoder(req.Request.Body).Decode(v)
}

// Write marshalls the value to JSON and set the Content-Type Header.
func (e entityXMLAccess) Write(resp *Response, status int, v interface{}) error {
	return writeXML(resp, status, e.ContentType, v)
}

// writeXML marshalls the value to JSON and set the Content-Type Header.
func writeXML(resp *Response, status int, contentType string, v interface{}) error {
	if v == nil {
		resp.WriteHeader(status)
		// do not write a nil representation
		return nil
	}
	if resp.prettyPrint {
		// pretty output must be created and written explicitly
		output, err := xml.MarshalIndent(v, " ", " ")
		if err != nil {
			return err
		}
		resp.Header().Set(HEADER_ContentType, contentType)
		resp.WriteHeader(status)
		_, err = resp.Write([]byte(xml.Header))
		if err != nil {
			return err
		}
		_, err = resp.Write(output)
		return err
	}
	// not-so-pretty
	resp.Header().Set(HEADER_ContentType, contentType)
	resp.WriteHeader(status)
	return xml.NewEncoder(resp).Encode(v)
}

// entityJSONAccess is a EntityReaderWriter for JSON encoding
type entityJSONAccess struct {
	// This is used for setting the Content-Type header when writing
	ContentType string
}

// Read unmarshalls the value from JSON
func (e entityJSONAccess) Read(req *Request, v interface{}) error {
	decoder := NewDecoder(req.Request.Body)
	decoder.UseNumber()
	return decoder.Decode(v)
}

// Write marshalls the value to JSON and set the Content-Type Header.
func (e entityJSONAccess) Write(resp *Response, status int, v interface{}) error {
	return writeJSON(resp, status, e.ContentType, v)
}

// write marshalls the value to JSON and set the Content-Type Header.
func writeJSON(resp *Response, status int, contentType string, v interface{}) error {
	if v == nil {
		resp.WriteHeader(status)
		// do not write a nil representation
		return nil
	}
	if resp.prettyPrint {
		// pretty output must be created and written explicitly
		output, err := MarshalIndent(v, "", " ")
		if err != nil {
			return err
		}
		resp.Header().Set(HEADER_ContentType, contentType)
		resp.WriteHeader(status)
		_, err = resp.Write(output)
		return err
	}
	// not-so-pretty
	resp.Header().Set(HEADER_ContentType, contentType)
	resp.WriteHeader(status)
	return NewEncoder(resp).Encode(v)
}
