'use strict';
/**
 * This plugin accumulates data chunks from the client into an array
 * property on the request or response, concats them on end. Then  
 * transforms the request or response based on 'accept' or 'content-type' 
 * headers. 
 * 
 * If the HTTP verb is GET and the Accept type does not match the 
 * response type, the plugin will attempt to transform it (from 
 * xml to json or vice versa).
 *
 * If the HTTP verb is NOT GET then the content-type is used. If the
 * content-type is set to 'json', then an attempt is made to transform to
 * 'xml' and vice-versa.
 *
 * This plugin can be disabled by sending the 'x-apigee-json2xml' http
 * header.
 *
 * Users should be aware that buffering large requests or responses in
 * memory can cause Apigee Edge Microgateway to run out of memory under
 * high load or with a large number of concurrent requests. So this plugin
 * should only be used when it is known that request/response bodies are small.
 */

var debug = require('debug')('plugin:json2xml');
//library to convert json to xml
var js2xmlparser = require("js2xmlparser");
//library to convert xml to json
var parseString = require("xml2js").parseString;
var util = require("util");

module.exports.init = function (config, logger, stats) {

	//initialize the variables to false

	//variables to control whether request and/or response transformation should take place
	var requestXML = false;
	var requestJSON = false;
	var responseJSON = false;
	var responseXML = false;
	//use these variables to determine the content type of response sent by target server
	var responseIsXML = false;
	var responseIsJSON = false;
	//flag to control whether transfornation should take place
	var disable = false;

	//method to accumulate responses
	function accumulateResponse(res, data) {
		debug('plugin accumulateResponse');
		if (!res._chunks) res._chunks = [];
		res._chunks.push(data);
	}

	//method to accumulate requests
	function accumulateRequest(req, data) {
		debug('plugin accumulateRequest');
		if (disable) return;
		if (!req._chunks) req._chunks = [];
		req._chunks.push(data);
	}
	
	return {

		onrequest: function(req, res, next) {
			debug('plugin onrequest');
			var method  = req.method.toLowerCase();
			var acceptType = req.headers['accept'];
			var contentType = req.headers['content-type'];

			if (req.headers['x-apigee-json2xml-disable']) disable = true;

			debug("accept header: " + acceptType);
			debug("content-type header: " + contentType);

			//if plugin is disabled don't process headers.
			if (!disable) {
				if (method === "get" && acceptType === "application/xml") {
					responseXML = true;
				} else if (method === "get" && acceptType === "application/json") {
					responseJSON = true;
				} else if (method !== "get" && contentType === "application/json") {
					requestJSON = true;
					responseJSON = true;
				} else if (method !== "get" && contentType === "application/xml") {
					requestXML = true;
					responseXML = true;
				}
			}
			
			debug("requestJSON flag is " + requestJSON);
			debug("responseJSON flag is " + responseJSON);

			debug("requestXML flag is " + requestXML);
			debug("responseXML flag is " + responseXML);

			debug("plugin disabled: " + disable);

			next();
		},
		// indicates start of target response
		// response headers and status code should be available at this time
		onresponse: function(req, res, next) {
			debug('plugin onresponse');
			//nothing to do on response
			next();
		},
		//
		ondata_request: function(req, res, data, next) {
			debug('plugin ondata_request');
			if (data && data.length > 0 && disable == false) accumulateRequest(req, data);
			next(null, null);
		},
		//
		//
		ondata_response: function(req, res, data, next) {
			debug('plugin ondata_response');
			if (data && data.length > 0 && disable == false) accumulateResponse(res, data);
			next(null, null);
		},
		//
		onend_request: function(req, res, data, next) {
			debug('plugin onend_request');
			if (data && data.length > 0 && disable == false) accumulateRequest(res, data);
			var content = null;
			if(req._chunks && req._chunks.length) {
				content = Buffer.concat(req._chunks);
			}
			delete req._chunks;

			//if pugin is disabled, don't do anything
			if (!disable) {
				if (requestJSON) {
					//the request needs to be transformed to xml before sending to 
					//the target server.

					//set request content type.
					req.setHeader('Content-Type', 'application/xml');
					next(null, js2xmlparser.parse("Root",JSON.parse(content)));
				} else if (requestXML) {
					//set request content type.
					req.setHeader('Content-Type', 'application/json');
					parseString(content.toString(), function(err, js){
						if (err) next (err);
						next(null, JSON.stringify(js));
					});
				} else { //do nothing
					next(null, content);
				}
			} else {
				next(null, content);
			}
		},
		//
		onend_response: function(req, res, data, next) {
			debug('plugin onend_request');
			if (data && data.length > 0 && disable == false) accumulateResponse(res, data);

			var contentType = res.getHeader('content-type');
			if (contentType === "application/xml") {
				responseIsXML = true;
			} else if (contentType === "application/json") {
				responseIsJSON = true;
			}

			debug("responseIsJSON flag is " + responseIsJSON);
			debug("responseIsXML flag is" + responseIsXML);


			var content = null;
			if(res._chunks && res._chunks.length) {
				content = Buffer.concat(res._chunks);
			}
			delete res._chunks;

			//if disabled don't do anything.
			if (!disable) {
				if (responseXML && responseIsJSON) {
					res.setHeader('Content-Type', 'application/xml');
					next(null, js2xmlparser.parse("Root",JSON.parse(content)));
				} else if (responseJSON && responseIsXML) {
					res.setHeader('Content-Type', 'application/json');
					parseString(content.toString(), function(err, js){
						if (err) next (err);
						next(null, JSON.stringify(js));
					});
				} else {
					next(null, content);
				}
			} else {
				next(null, content);
			}
		}		
	};
}