package de.retest.recheck.review.workers;

import static de.retest.recheck.configuration.ProjectConfiguration.RECHECK_IGNORE;
import static de.retest.recheck.configuration.ProjectConfiguration.RECHECK_IGNORE_JSRULES;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import de.retest.recheck.ignore.CacheFilter;
import de.retest.recheck.ignore.JSFilterImpl;
import de.retest.recheck.ignore.RecheckIgnoreUtil;
import de.retest.recheck.review.GlobalIgnoreApplier;
import de.retest.recheck.review.GlobalIgnoreApplier.PersistableGlobalIgnoreApplier;
import de.retest.recheck.review.counter.Counter;
import de.retest.recheck.review.ignore.io.Loaders;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class LoadFilterWorker {

	private final Counter counter;
	private final Path ignoreFilesBasePath;

	public LoadFilterWorker( final Counter counter ) {
		this( counter, null );
	}

	public LoadFilterWorker( final Counter counter, final Path ignoreFilesBasePath ) {
		this.counter = counter;
		this.ignoreFilesBasePath = ignoreFilesBasePath;
	}

	public GlobalIgnoreApplier load() throws IOException {
		final Optional<Path> projectIgnoreFile = RecheckIgnoreUtil.getProjectIgnoreFile( RECHECK_IGNORE );
		final Optional<Path> userIgnoreFile = RecheckIgnoreUtil.getUserIgnoreFile( RECHECK_IGNORE );
		final Optional<Path> suiteIgnoreFile =
				RecheckIgnoreUtil.getSuiteIgnoreFile( RECHECK_IGNORE, ignoreFilesBasePath );
		final Stream<String> concatIgnoreFileLines =
				Stream.concat( getIgnoreFileLines( projectIgnoreFile ), getIgnoreFileLines( userIgnoreFile ) );
		final Stream<String> allIgnoreFileLines =
				Stream.concat( concatIgnoreFileLines, getIgnoreFileLines( suiteIgnoreFile ) );

		final PersistableGlobalIgnoreApplier ignoreApplier = Loaders.filter().load( allIgnoreFileLines ) //
				.collect( Collectors.collectingAndThen( Collectors.toList(), PersistableGlobalIgnoreApplier::new ) );
		final GlobalIgnoreApplier result = GlobalIgnoreApplier.create( counter, ignoreApplier );

		final Optional<Path> projectIgnoreRuleFile = RecheckIgnoreUtil.getProjectIgnoreFile( RECHECK_IGNORE_JSRULES );
		final Optional<Path> userIgnoreRuleFile = RecheckIgnoreUtil.getUserIgnoreFile( RECHECK_IGNORE_JSRULES );
		final Optional<Path> suiteIgnoreRuleFile =
				RecheckIgnoreUtil.getSuiteIgnoreFile( RECHECK_IGNORE_JSRULES, ignoreFilesBasePath );
		projectIgnoreRuleFile
				.ifPresent( file -> result.addWithoutCounting( new CacheFilter( new JSFilterImpl( file ) ) ) );
		suiteIgnoreRuleFile
				.ifPresent( file -> result.addWithoutCounting( new CacheFilter( new JSFilterImpl( file ) ) ) );
		userIgnoreRuleFile
				.ifPresent( file -> result.addWithoutCounting( new CacheFilter( new JSFilterImpl( file ) ) ) );

		return result;
	}

	private Stream<String> getIgnoreFileLines( final Optional<Path> ignoreFile ) throws IOException {
		if ( ignoreFile.isPresent() ) {
			log.info( "Reading ignore file from {}.", ignoreFile.get() );
			return Files.lines(
					ignoreFile.orElseThrow( () -> new NoSuchFileException( "No '" + RECHECK_IGNORE + "' found." ) ) );
		}
		log.info( "Ignoring missing ignore file." );
		return Stream.empty();
	}

	public Counter getCounter() {
		return counter;
	}
}

@@ -1465,36 +1465,37 @@
 %09%09final 
-Optional%3CPath%3E suite
+Stream%3CString%3E concat
 IgnoreFi
@@ -1500,100 +1500,118 @@
 File
+Lines
  =%0A%09%09%09%09
-RecheckIgnoreUtil.getSuiteIgnoreFile( RECHECK_IGNORE, ignoreFilesBasePath );%0A%09%09final 
+Stream.concat( getIgnoreFileLines( projectIgnoreFile ), getIgnoreFileLines( userIgnoreFile ) );%0A%09%09
 Stre
@@ -1613,38 +1613,35 @@
 %09Stream%3CString%3E 
-concat
+all
 IgnoreFileLines 
@@ -1645,132 +1645,199 @@
 es =
-%0A%09%09%09%09Stream.concat( getIgnoreFileLines( projectIgnoreFile ), getIgnoreFileLines( userIgnoreFile ) );%0A%09%09final Stream%3CString%3E 
+ concatIgnoreFileLines;%0A%0A%09%09if ( ignoreFilesBasePath != null ) %7B%0A%09%09%09final Optional%3CPath%3E suiteIgnoreFile =%0A%09%09%09%09%09RecheckIgnoreUtil.getSuiteIgnoreFile( RECHECK_IGNORE, ignoreFilesBasePath );%0A%09%09%09
 allI
@@ -1844,37 +1844,33 @@
 gnoreFileLines =
-%0A%09%09%09%09
+ 
 Stream.concat( c
@@ -1927,24 +1927,28 @@
 oreFile ) );
+%0A%09%09%7D
 %0A%0A%09%09final Pe
@@ -2461,142 +2461,8 @@
  );%0A
-%09%09final Optional%3CPath%3E suiteIgnoreRuleFile =%0A%09%09%09%09RecheckIgnoreUtil.getSuiteIgnoreFile( RECHECK_IGNORE_JSRULES, ignoreFilesBasePath );%0A
 %09%09pr
@@ -2583,21 +2583,20 @@
  ) );%0A%09%09
-suite
+user
 IgnoreRu
@@ -2694,38 +2694,216 @@
 ( file ) ) ) );%0A
+%0A
 %09%09
-user
+if ( ignoreFilesBasePath != null ) %7B%0A%09%09%09final Optional%3CPath%3E suiteIgnoreRuleFile =%0A%09%09%09%09%09RecheckIgnoreUtil.getSuiteIgnoreFile( RECHECK_IGNORE_JSRULES, ignoreFilesBasePath );%0A%09%09%09suite
 IgnoreRuleFile%0A%09
@@ -2893,32 +2893,33 @@
 eIgnoreRuleFile%0A
+%09
 %09%09%09%09.ifPresent( 
@@ -2997,24 +2997,28 @@
 ile ) ) ) );
+%0A%09%09%7D
 %0A%0A%09%09return r

Check for suite ignore to not trigger when using review