package de.retest.recheck.persistence;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

import java.io.File;
import java.net.URI;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.rule.PowerMockRule;

import de.retest.junit.vintage.SystemProperty;
import de.retest.recheck.RecheckProperties;
import de.retest.recheck.persistence.PersistenceFactory.DynamicLoadPersistenceProxy;
import de.retest.recheck.persistence.bin.KryoPersistence;
import de.retest.recheck.persistence.xml.XmlFolderPersistence;
import de.retest.recheck.persistence.xml.XmlTransformer;
import de.retest.recheck.persistence.xml.XmlZipPersistence;
import de.retest.testutils.FileUtils;

@PrepareForTest( { PersistenceFactory.class, XmlZipPersistence.class, XmlFolderPersistence.class } )
public class PersistenceFactoryTest {

	@Rule
	public MockitoRule mockitoRule = MockitoJUnit.rule();

	@Rule
	public PowerMockRule powerMockRule = new PowerMockRule();

	@Rule
	public SystemProperty fileFormat = new SystemProperty( RecheckProperties.FILE_OUTPUT_FORMAT_PROPERTY_KEY, null );

	private PersistenceFactory factory;

	@Mock
	public XmlZipPersistence<Persistable> xmlZipPersistence;

	@Mock
	public XmlFolderPersistence<Persistable> xmlFolderPersistence;

	@Before
	public void setUp() throws Exception {
		factory = new PersistenceFactory( (XmlTransformer) null );
		PowerMockito.whenNew( XmlZipPersistence.class ).withAnyArguments().thenReturn( xmlZipPersistence );
		PowerMockito.whenNew( XmlFolderPersistence.class ).withAnyArguments().thenReturn( xmlFolderPersistence );
	}

	@Test
	public void returns_dynamic_load_persistence() {
		final Persistence<? extends Persistable> persistence = factory.getPersistence();
		assertThat( persistence ).isInstanceOf( DynamicLoadPersistenceProxy.class );
	}

	@Test
	public void load_starts_zip_persistence_if_its_a_zip_file() throws Exception {
		final URI identifier = FileUtils.getFileUriForClasspathRelativPath( "/persistence/empty.zip" );
		factory.getPersistence().load( identifier );

		verify( xmlZipPersistence ).load( identifier );
		verify( xmlFolderPersistence, never() ).load( identifier );
	}

	@Test
	public void load_starts_folder_persistence_if_its_a_folder() throws Exception {
		final URI identifier = FileUtils.getFileUriForClasspathRelativPath( "/persistence" );
		factory.getPersistence().load( identifier );

		verify( xmlFolderPersistence ).load( identifier );
		verify( xmlZipPersistence, never() ).load( identifier );
	}

	@Test
	public void save_use_zip_persistence_when_zip_is_default() throws Exception {
		final URI identifier = new URI( "" );
		final Persistable element = mock( Persistable.class );
		fileFormat.setValue( FileOutputFormat.ZIP.name() );

		factory.getPersistence().save( identifier, element );

		verify( xmlZipPersistence ).save( identifier, element );
		verify( xmlFolderPersistence, never() ).save( identifier, element );
	}

	@Test
	public void save_use_folder_persistence_when_folder_is_default() throws Exception {
		final URI identifier = new URI( "" );
		final Persistable element = mock( Persistable.class );
		fileFormat.setValue( FileOutputFormat.PLAIN.name() );

		factory.getPersistence().save( identifier, element );

		verify( xmlFolderPersistence ).save( identifier, element );
		verify( xmlZipPersistence, never() ).save( identifier, element );
	}

	@Test
	public void load_persistence_for_result_replay_should_be_kryo() throws Exception {
		final URI identifier = new File( "test.report" ).toURI();
		final Persistence<Persistable> loadPersistence = factory.getLoadPersistenceForIdentifier( identifier );
		assertThat( loadPersistence ).isInstanceOf( KryoPersistence.class );
	}

	@Test
	public void save_persistence_for_result_replay_should_be_kryo() throws Exception {
		final URI identifier = new File( "test.report" ).toURI();
		final Persistence<Persistable> savePersistence = factory.getSavePersistenceForIdentifier( identifier );
		assertThat( savePersistence ).isInstanceOf( KryoPersistence.class );
	}

}

@@ -29,24 +29,107 @@
 rsistence;%0A%0A
+import static de.retest.recheck.RecheckProperties.FILE_OUTPUT_FORMAT_PROPERTY_KEY;%0A
 import stati
@@ -174,16 +174,16 @@
 rtThat;%0A
-
 import s
@@ -408,24 +408,91 @@
 junit.Test;%0A
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;%0A
 import org.m
@@ -755,99 +755,8 @@
 e;%0A%0A
-import de.retest.junit.vintage.SystemProperty;%0Aimport de.retest.recheck.RecheckProperties;%0A
 impo
@@ -1077,46 +1077,8 @@
 nce;
-%0Aimport de.retest.testutils.FileUtils;
 %0A%0A@P
@@ -1364,112 +1364,92 @@
 lic 
-SystemProperty fileFormat = new SystemProperty( RecheckProperties.FILE_OUTPUT_FORMAT_PROPERTY_KEY, null 
+final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties(
 );%0A%0A
@@ -3045,36 +3045,68 @@
 ss );%0A%09%09
-fileFormat.setValue(
+System.setProperty( FILE_OUTPUT_FORMAT_PROPERTY_KEY,
  FileOut
@@ -3516,28 +3516,60 @@
 ;%0A%09%09
-fileFormat.setValue(
+System.setProperty( FILE_OUTPUT_FORMAT_PROPERTY_KEY,
  Fil

Replace custom sysprop mechanism