package org.dataone.audit;

import static org.junit.Assert.*;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import org.dataone.client.CNode;
import org.dataone.client.audit.AuditCNode;
import org.dataone.service.exceptions.BaseException;
import org.dataone.service.exceptions.InvalidRequest;
import org.dataone.service.exceptions.InvalidToken;
import org.dataone.service.exceptions.NotAuthorized;
import org.dataone.service.exceptions.NotFound;
import org.dataone.service.exceptions.NotImplemented;
import org.dataone.service.exceptions.ServiceFailure;
import org.dataone.service.types.v1.Identifier;
import org.dataone.service.types.v1.ObjectInfo;
import org.dataone.service.types.v1.ObjectList;
import org.junit.Before;
import org.junit.Test;

public class TidyTesting {

	private final static String CN_BASEURL = "https://cn-ucsb-1.dataone.org/cn";
	private static ObjectList PAGED_OBJECTLIST;
	
	
	// the overshoot is to all us to try to retrieve more than stated
	// a bit goofy, but want to allow the testListObjects test to be explicit about
	// what it's doing
	private ObjectList getAllObjectInfos(AuditCNode cn, Integer overshoot) 
	throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, ServiceFailure {
		
		ObjectList ol = cn.listObjects(null, null, null, null, null, 0);
		int total = ol.getTotal();
		
		if (PAGED_OBJECTLIST == null) {
			int requestedPageSize = 10000;
			PAGED_OBJECTLIST = APITestUtils.pagedListObjects(cn, null, null, null, null, 0, total+overshoot, requestedPageSize);
		}
		return PAGED_OBJECTLIST;
	}

	
	@Before
	public void setUp() throws Exception {
	}

	@Test
	public final void testListObjects() throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, ServiceFailure {
		AuditCNode cn = new AuditCNode(CN_BASEURL);
		ObjectList ol = cn.listObjects(null, null, null, null, null, 0);
		int total = ol.getTotal();
		
		Integer overshoot = 100;
		// overshoot means we're asking for more than the node says it has
		ol = getAllObjectInfos(cn,overshoot);

		int count = ol.sizeObjectInfoList();
		int newTotal = ol.getTotal();
		assertTrue("1. new Total should equal the old total", total == newTotal);
		assertTrue("2. retrieved total should equal the count", count == newTotal);
	}
	
	

	
	@Test public final void testSystemMetadataRetrieval() 
	throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, ServiceFailure 
	{
		AuditCNode cn = new AuditCNode(CN_BASEURL);
		List<Identifier> pids;

		// TODO need to provide a list of pids with better distribution
		
		ObjectList ol = getAllObjectInfos(cn, null);
		pids = new LinkedList<Identifier>();
		int i = 0;
		for (ObjectInfo oi : ol.getObjectInfoList()) {
			if (i % 4000 == 0)
				pids.add(oi.getIdentifier());
			i++;
		}
		
		int exceptionCount = 0;
		int pidCount = 0;
		List<String> sysmetaList = new LinkedList<String>(); 
		for (Identifier pid : pids) {
			pidCount++;
			StringBuffer sb = new StringBuffer();
			try {
				sb.append(pid.getValue());
				cn.getSystemMetadata(pid);
				sb.append("  OK");
			} catch (BaseException e) {
				sb.append(String.format(
					"EXCEPTION: %s-%s / %s",
					e.getClass().getSimpleName(),
					e.getDescription(),
					e.getCause() != null ? e.getCause().getClass().getSimpleName() : null
					)
					);
				exceptionCount++;
			}
			sysmetaList.add(sb.toString());
		}
		System.out.println("Sysmetas for retrieval");
		for (String s : sysmetaList) {
			System.out.println(s);
		}
		System.out.println("Number of pids: " + pidCount);
		System.out.println(("number of exceptions: " + exceptionCount));
		
		
		assertTrue("No exceptions encountered when retrieving systemMetadata", exceptionCount==0);
	}

}