/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.    
 */
package org.apache.tuscany.sca.binding.atom;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;

import junit.framework.Assert;

import org.apache.abdera.Abdera;
import org.apache.abdera.factory.Factory;
import org.apache.abdera.i18n.iri.IRI;
import org.apache.abdera.model.Collection;
import org.apache.abdera.model.Content;
import org.apache.abdera.model.Entry;
import org.apache.abdera.model.Feed;
import org.apache.abdera.parser.Parser;
import org.apache.abdera.protocol.Response.ResponseType;
import org.apache.abdera.protocol.client.AbderaClient;
import org.apache.abdera.protocol.client.ClientResponse;
import org.apache.abdera.protocol.client.RequestOptions;
import org.apache.tuscany.sca.host.embedded.SCADomain;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * Tests use of server provided feed entity tags for Atom binding in Tuscany.
 * Tests conditional gets (e.g. get if-none-match) or conditional posts (post if-match)
 * using entity tags and last modified entries in headers. 
 * Uses the SCA provided Provider composite to act as a server.
 * Uses the Abdera provided Client to act as a client.
 */
public class ProviderFeedEntityTagsTestCase {
	public final static String providerURI = "http://localhost:8084/customer";
	protected static SCADomain scaProviderDomain;
	protected static CustomerClient testService;
    protected static Abdera abdera;
    protected static AbderaClient client;
    protected static Parser abderaParser;    
    protected static String eTag;
    protected static Date lastModified;
    protected static final SimpleDateFormat dateFormat = new SimpleDateFormat( "EEE, dd MMM yyyy HH:mm:ss Z" ); // RFC 822 date time

	@BeforeClass
	public static void init() throws Exception {
		System.out.println(">>>ProviderFeedEntityTagsTestCase.init");
		scaProviderDomain = SCADomain.newInstance("org/apache/tuscany/sca/binding/atom/Provider.composite");
		abdera = new Abdera();
		client = new AbderaClient(abdera);
		abderaParser = Abdera.getNewParser();
	}

    @AfterClass
    public static void destroy() throws Exception {
        System.out.println(">>>ProviderFeedEntityTagsTestCase.destroy");
        if (scaProviderDomain != null) {
            scaProviderDomain.close();
        }
    }

	@Test
	public void testPrelim() throws Exception {
		Assert.assertNotNull(scaProviderDomain);
		Assert.assertNotNull( client );
	}
			
	@Test
    public void testFeedBasics() throws Exception {		
		System.out.println(">>>ProviderFeedEntityTagsTestCase.testFeedBasics");
		// Normal feed request
		ClientResponse res = client.get(providerURI);
		Assert.assertNotNull(res);
		try {
			// Assert feed provided since no predicates
			Assert.assertEquals(200, res.getStatus());
			Assert.assertEquals(ResponseType.SUCCESS, res.getType());
	    	// AtomTestCaseUtils.printResponseHeaders( "Feed response headers:", "   ", res );
	    	// System.out.println("Feed response content:");
	    	// AtomTestCaseUtils.prettyPrint(abdera, res.getDocument());

	    	// Perform other tests on feed.
	    	// Warning. AbderaClient.getEntityTag is very particular on tag pattern.
			// Document<Feed> doc = res.getDocument();
	    	String body = read( res.getInputStream() );
			// RFC 4287 requires non-null id, title, updated elements
			Assert.assertTrue( -1 != body.indexOf( "</id>" ));
			Assert.assertTrue( -1 != body.indexOf( "</title>" ));
			Assert.assertTrue( -1 != body.indexOf( "</updated>" ));
			
			eTag = res.getHeader("ETag");
			Assert.assertNotNull( eTag );
			lastModified = res.getLastModified();
			Assert.assertNotNull( lastModified );
		} finally {
			res.release();
		}
	}		

	@Test
    public void testUnmodifiedGetIfMatch() throws Exception {		
		System.out.println(">>>ProviderFeedEntityTagsTestCase.testFeedUnmodifiedGetIfMatch");
		// Feed request with predicates
		RequestOptions opts = new RequestOptions();
		final String contentType = "application/atom+xml"; 
		opts.setContentType(contentType);
		opts.setHeader( "If-Match", eTag);
		
		ClientResponse res = client.get(providerURI, opts);
		Assert.assertNotNull(res);
		try {
	    	String thisETag = res.getHeader("ETag");
			Assert.assertNotNull( thisETag );
			Date thisLastModified = res.getLastModified();
			Assert.assertNotNull( thisLastModified );
                        
			// Should return 200 - Feed provided since it matches etag.
			Assert.assertEquals(200, res.getStatus());
			Assert.assertEquals(ResponseType.SUCCESS, res.getType());
	    	// AtomTestCaseUtils.printResponseHeaders( "Feed response headers:", "   ", res );
	    	// System.out.println("Feed response content:");
	    	// AtomTestCaseUtils.prettyPrint(abdera, res.getDocument());
		} finally {
			res.release();
		}
	}		

	@Test
    public void testUnmodifiedGetIfNoneMatch() throws Exception {		
		System.out.println(">>>ProviderFeedEntityTagsTestCase.testFeedUnmodifiedGetIfNoneMatch");
		// Feed request with predicates
		RequestOptions opts = new RequestOptions();
		final String contentType = "application/atom+xml"; 
		opts.setContentType(contentType);
		opts.setHeader( "If-None-Match", eTag);
		
		ClientResponse res = client.get(providerURI, opts);
		Assert.assertNotNull(res);
		try {
			// Should return 304 - Feed not provided since it matches ETag.
			Assert.assertEquals(304, res.getStatus());
		} finally {
			res.release();
		}
	}		

	@Test
    public void testUnmodifiedGetIfUnModified() throws Exception {		
		System.out.println(">>>ProviderFeedEntityTagsTestCase.testFeedUnmodifiedGetIfUnModified");
		// Feed request with predicates
		RequestOptions opts = new RequestOptions();
		final String contentType = "application/atom+xml"; 
		opts.setContentType(contentType);
		opts.setHeader( "If-Unmodified-Since", dateFormat.format( new Date() ));
		
		ClientResponse res = client.get(providerURI, opts);
		Assert.assertNotNull(res);
		try {
            // Should return 200 - Feed provided since feed is unmodified since.
            Assert.assertEquals(200, res.getStatus());
            Assert.assertEquals(ResponseType.SUCCESS, res.getType());
		} finally {
			res.release();
		}
	}		

	@Test
    public void testUnmodifiedGetIfModified() throws Exception {		
		System.out.println(">>>ProviderFeedEntityTagsTestCase.testFeedUnmodifiedGetIfModified");
        // Feed request with predicates
        RequestOptions opts = new RequestOptions();
        final String contentType = "application/atom+xml"; 
        opts.setContentType(contentType);
        opts.setHeader( "If-Modified-Since", dateFormat.format( new Date() ));
        
        ClientResponse res = client.get(providerURI, opts);
        Assert.assertNotNull(res);
        try {
            // Should return 304 - Feed not provided since feed is unmodified.
            Assert.assertEquals(304, res.getStatus());
        } finally {
            res.release();
        }

		// Feed request with predicates
		opts = new RequestOptions();
		opts.setContentType(contentType);
		opts.setHeader( "If-Modified-Since", dateFormat.format( new Date( 0 ) ));
		
		res = client.get(providerURI, opts);
		Assert.assertNotNull(res);
		try {
			// Should return 200 - Feed provided since feed is changed.
			Assert.assertEquals(200, res.getStatus());
			Assert.assertEquals(ResponseType.SUCCESS, res.getType());

			String thisETag = res.getHeader("ETag");
			Assert.assertNotNull( thisETag );
			Date thisLastModified = res.getLastModified();
			Assert.assertNotNull( thisLastModified );                        
		} finally {
			res.release();
		}
	}		

	@Test
    public void testModifiedGetIfNoneMatch() throws Exception {		
		System.out.println(">>>ProviderFeedEntityTagsTestCase.testFeedModifiedGetIfNoneMatch");
		// Post some new content to the feed.
		Factory factory = abdera.getFactory();
		String customerName = "Fred Farkle";
		Entry entry = factory.newEntry();
		entry.setTitle("customer " + customerName);
		entry.setUpdated(new Date());
		entry.addAuthor("Apache Tuscany");
		Content content = abdera.getFactory().newContent();
		content.setContentType(Content.Type.TEXT);
		content.setValue(customerName);
		entry.setContentElement(content);

		RequestOptions opts = new RequestOptions();
		String contentType = "application/atom+xml; type=entry"; 
		opts.setContentType(contentType);
		IRI colUri = new IRI(providerURI).resolve("customer");
		ClientResponse res = client.post(colUri.toString(), entry, opts);
			
		// Feed request with predicates
		opts = new RequestOptions();
		contentType = "application/atom+xml"; 
		opts.setContentType(contentType);
		opts.setHeader( "If-None-Match", eTag);
		
		res = client.get(providerURI, opts);
		Assert.assertNotNull(res);
		try {
			// Should return 304 - Feed not provided since it matches ETag.
			Assert.assertEquals(304, res.getStatus());
	    	// AtomTestCaseUtils.printResponseHeaders( "Feed response headers:", "   ", res );
	    	// System.out.println("Feed response content:");
	    	// AtomTestCaseUtils.prettyPrint(abdera, res.getDocument());
		} finally {
			res.release();
		}
	}		

	@Test
    public void testModifiedGetIfMatch() throws Exception {		
		System.out.println(">>>ProviderFeedEntityTagsTestCase.testFeedModifiedGetIfMatch");
		// Feed request with predicates
		RequestOptions opts = new RequestOptions();
		final String contentType = "application/atom+xml"; 
		opts.setContentType(contentType);
		opts.setHeader( "If-Match", eTag);
		
		ClientResponse res = client.get(providerURI, opts);
		Assert.assertNotNull(res);
		try {
	    	String thisETag = res.getHeader("ETag");
			Assert.assertNotNull( thisETag );
			Date thisLastModified = res.getLastModified();
			Assert.assertNotNull( thisLastModified );
                        
			// Should return 200 - value since feed matches eTag
			Assert.assertEquals(200, res.getStatus());
			Assert.assertEquals(ResponseType.SUCCESS, res.getType());
			
	    	// AtomTestCaseUtils.printResponseHeaders( "Feed modified if-none-match response headers:", "   ", res );
	    	// System.out.println("Feed response content:");
	    	// AtomTestCaseUtils.prettyPrint(abdera, res.getDocument());
		} finally {
			res.release();
		}
	}		

	@Test
    public void testModifiedGetIfUnModified() throws Exception {		
		System.out.println(">>>ProviderFeedEntityTagsTestCase.testFeedModifiedGetIfUnModified");
		// Feed request with predicates
		RequestOptions opts = new RequestOptions();
		final String contentType = "application/atom+xml"; 
		opts.setContentType(contentType);
		opts.setHeader( "If-Unmodified-Since", dateFormat.format( previousSecond(lastModified) ));
		
		ClientResponse res = client.get(providerURI, opts);
		Assert.assertNotNull(res);
		try {
			// Should return 412 - Feed not provided since feed is modified since.			
			Assert.assertEquals(412, res.getStatus());
		} finally {
			res.release();
		}
	}		

	@Test
    public void testModifiedGetIfModified() throws Exception {		
		System.out.println(">>>ProviderFeedEntityTagsTestCase.testFeedModifiedGetIfModified");
		// Feed request with predicates
		RequestOptions opts = new RequestOptions();
		final String contentType = "application/atom+xml"; 
		opts.setContentType(contentType);
		opts.setHeader( "If-Modified-Since", dateFormat.format( previousSecond(lastModified) ));
		
		ClientResponse res = client.get(providerURI, opts);
		Assert.assertNotNull(res);
		try {
			// Should return 200 - Feed provided since feed is changed.
			Assert.assertEquals(200, res.getStatus());
			Assert.assertEquals(ResponseType.SUCCESS, res.getType());

			String thisETag = res.getHeader("ETag");
			Assert.assertNotNull( thisETag );
			Date thisLastModified = res.getLastModified();
			Assert.assertNotNull( thisLastModified );                        
		} finally {
			res.release();
		}
	}		


	public static void printFeed( String title, String indent, Feed feed ) {
		if ( feed == null ) {
			System.out.println( title + " feed is null");
			return;
		}
			
		System.out.println( title );
		System.out.println( indent + "id=" + feed.getId() );
		System.out.println( indent + "title=" + feed.getTitle() );
		System.out.println( indent + "updated=" + feed.getUpdated() );
		System.out.println( indent + "author=" + feed.getAuthor() );
		Collection collection = feed.getCollection();
		if ( collection == null ) {
			System.out.println( indent + "collection=null" );
		} else {
			System.out.println( indent + "collection=" + collection );
		}
		// System.out.println( indent + "collection size=" + feed.getCollection() );
		// for (Collection collection : workspace.getCollections()) {
		//    if (collection.getTitle().equals("customers")) {
		//       String expected = uri + "customers";
		//       String actual = collection.getResolvedHref().toString();
		//       assertEquals(expected, actual);
		//    }
		// }

	}

	/**
	 * Read response ream from the given socket.
	 * @param socket
	 * @return
	 * @throws IOException
	 */
	private static String read(InputStream inputStream) throws IOException {
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new InputStreamReader( inputStream ));
			StringBuffer sb = new StringBuffer();
			String str;
			while ((str = reader.readLine()) != null) {
				sb.append(str);
			}
			return sb.toString();
		} finally {
			if (reader != null) {
				reader.close();
			}
		}
	}

    /**
     * Subtract one second from a date
     * @param date with millisecond precision
     * @return date with one second subtracted
     */
    private Date previousSecond(Date date) {
        return new Date(date.getTime() - 1000);
    }
}
