package com.nifty.cloud.ncs;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.util.EntityUtils;

import com.nifty.cloud.ncs.http.HttpRequest;

/**
 * HTTP要求のボディを保持するクラスです。
 *
 */
public class NiftyCloudInputStreamEntity implements HttpEntity
{
	private static final Log log = LogFactory.getLog(NiftyCloudClient.class);
	private InputStreamEntity inputStreamEntity;
	private InputStream content;
	private boolean first = true;

    /**
     * 指定したHTTP要求内容を使用して新しいNiftyCloudInputStreamEntityを生成します。
     *
     * @param request
     *  HTTP要求内容
     */
	public NiftyCloudInputStreamEntity(HttpRequest request)
	{
		if (request == null) {
			throw (new IllegalArgumentException("Source request may not be null."));
		}

		long contentLength = -1;
		try {
			String lengthString = request.getHeader("Content-Length");
			if (lengthString != null) {
				contentLength = Long.parseLong(lengthString);
			}
		} catch (NumberFormatException e) {
			log.warn("Can't parse content length from request. Buffering contents in memory.");
		}

		this.content = request.getContent();
		inputStreamEntity = new InputStreamEntity(content, contentLength);
		request.removeHeader("Content-Length");
	}

	@Override
	public boolean isRepeatable()
	{
		if (content.markSupported() || inputStreamEntity.isRepeatable()) {
			return (true);
		}
		return (false);
	}

	@Override
	public void consumeContent() throws IOException
	{
		EntityUtils.consume(this);
	}

	@Override
	public InputStream getContent() throws IOException, IllegalStateException
	{
		return (inputStreamEntity.getContent());
	}

	@Override
	public Header getContentEncoding()
	{
		return (inputStreamEntity.getContentEncoding());
	}

	@Override
	public long getContentLength()
	{
		return (inputStreamEntity.getContentLength());
	}

	@Override
	public Header getContentType()
	{
		return (inputStreamEntity.getContentType());
	}

	@Override
	public boolean isChunked()
	{
		return (inputStreamEntity.isChunked());
	}

	@Override
	public boolean isStreaming()
	{
		return (inputStreamEntity.isStreaming());
	}

	@Override
	public void writeTo(OutputStream output) throws IOException
	{
		if (first == false && isRepeatable()) {
			content.reset();
		}

		first = false;
		inputStreamEntity.writeTo(output);
	}

}
