package uk.ac.ebi.quickgo.index.annotation.coterms;

import uk.ac.ebi.quickgo.index.annotation.Annotation;

import java.io.File;
import java.util.List;
import java.util.function.Predicate;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.transform.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

/**
 * @author Tony Wardell
 * Date: 08/09/2016
 * Time: 11:07
 * Created with IntelliJ IDEA.
 */
@Configuration
public class CoTermConfiguration {

    public static final String[] FF_COL_NAMES = {"target", "comparedTerm", "probabilityRatio", "similarityRatio",
            "together", "compared"};
    public static final String DELIMITER = "\t";

    @Value("${indexing.coterms.dir}")
    private String path;

    public static final String COSTATS_MANUAL_COMPLETION_STEP_NAME = "costatsManualSummarizationStep";
    public static final String COSTATS_ALL_COMPLETION_STEP_NAME = "costatsAllSummarizationStep";

    @Bean
    AnnotationCoTermsAggregator annotationCoTermsAggregatorMan(){
        return new AnnotationCoTermsAggregator();
    }

    @Bean
    AnnotationCoTermsAggregator annotationCoTermsAggregatorAll(){
        return new AnnotationCoTermsAggregator();
    }

    @Bean
    public ItemProcessor<Annotation, Annotation> coStatsManual(AnnotationCoTermsAggregator annotationCoTermsAggregatorMan){
        Predicate<Annotation> toBeProcessed = t -> !"IEA".equals(t.evidenceCode);
        return new AnnotationCoTermsProcessor(annotationCoTermsAggregatorMan, toBeProcessed);
    }

    @Bean
    public ItemProcessor<Annotation, Annotation> coStatsAll(AnnotationCoTermsAggregator annotationCoTermsAggregatorAll){
        Predicate<Annotation> toBeProcessed = t -> true;
        return new AnnotationCoTermsProcessor(annotationCoTermsAggregatorAll, toBeProcessed);
    }

    @Bean
    public CoTermsStepExecutionListener coTermsStepExecutionListener(AnnotationCoTermsAggregator annotationCoTermsAggregatorAll,
            AnnotationCoTermsAggregator annotationCoTermsAggregatorMan){
        return new CoTermsStepExecutionListener(annotationCoTermsAggregatorAll, annotationCoTermsAggregatorMan);

    }

    @Bean
    public static ItemProcessor<String, List<CoOccurringTerm>> coStatsManualItemProcessor(AnnotationCoTermsAggregator annotationCoTermsAggregatorMan){
        CoStatsItemProcessor coStatsItemProcessor = new CoStatsItemProcessor(annotationCoTermsAggregatorMan);
        return coStatsItemProcessor;
    }

    @Bean
    public static ItemProcessor<String, List<CoOccurringTerm>> coStatsAllItemProcessor(AnnotationCoTermsAggregator annotationCoTermsAggregatorAll){
        CoStatsItemProcessor coStatsItemProcessor = new CoStatsItemProcessor(
                annotationCoTermsAggregatorAll.totalOfAnnotatedGeneProducts(),
                annotationCoTermsAggregatorAll.termGPCount(),
                annotationCoTermsAggregatorAll.termToTermOverlapMatrix());
        return coStatsItemProcessor;
    }

    @Bean
    public ItemReader<String> coStatsManualItemReader(AnnotationCoTermsAggregator annotationCoTermsAggregatorMan){
        return new CoStatsForTermItemReader(annotationCoTermsAggregatorMan);
    }

    @Bean
    public ItemReader<String> coStatsAllItemReader(AnnotationCoTermsAggregator annotationCoTermsAggregatorAll){
        return new CoStatsForTermItemReader(annotationCoTermsAggregatorAll);
    }


    @Bean
    ItemWriter<List<CoOccurringTerm>> coStatManualFlatFileWriter() {
        return listItemFlatFileWriter("CoStatsManual" );
    }

    @Bean
    ItemWriter<List<CoOccurringTerm>> coStatsAllFlatFileWriter() {
        return listItemFlatFileWriter("CoStatsAll" );
    }


    public File getFilePath() {
        File file = new File(path);
            if(!file.exists()){
                file.mkdir();
            }
            return file;
    }

    private ListItemWriter<CoOccurringTerm> listItemFlatFileWriter(String fileName) {
        ListItemWriter<CoOccurringTerm> listWriter = new ListItemWriter<>(flatFileWriter(fileName));
        listWriter.setLineAggregator(new PassThroughLineAggregator<>()); //this shouldn't do anything
        return listWriter;
    }

    private FlatFileItemWriter<CoOccurringTerm> flatFileWriter(String fileName) {
        FlatFileItemWriter<CoOccurringTerm> ffw = new FlatFileItemWriter<>();
        ffw.setLineAggregator(lineAggregator());
        Resource outputFile = new FileSystemResource(new File(getFilePath(), fileName ));
        ffw.setResource(outputFile);
        return ffw;
    }

    private FieldExtractor<CoOccurringTerm> beanWrapperFieldExtractor(){
        BeanWrapperFieldExtractor<CoOccurringTerm> beanWrapperFieldExtractor = new BeanWrapperFieldExtractor();
        beanWrapperFieldExtractor.setNames(FF_COL_NAMES);
        return beanWrapperFieldExtractor;
    }

    private LineAggregator<CoOccurringTerm> lineAggregator(){
        DelimitedLineAggregator<CoOccurringTerm> delimitedLineAggregator = new DelimitedLineAggregator<>();
        delimitedLineAggregator.setDelimiter(DELIMITER);
        delimitedLineAggregator.setFieldExtractor(beanWrapperFieldExtractor());
        return delimitedLineAggregator;
    }
}

@@ -1665,28 +1665,53 @@
 notation%3E co
-Stat
+OccuringGoTermsFromAnnotation
 sManual(Anno
@@ -1872,34 +1872,40 @@
 new 
-AnnotationC
+CoOccuringG
 oTerms
-Processor
+FromAnnotations
 (ann
@@ -2013,28 +2013,53 @@
 notation%3E co
-Stat
+OccuringGoTermsFromAnnotation
 sAll(Annotat
@@ -2192,34 +2192,40 @@
 new 
-AnnotationC
+CoOccuringG
 oTerms
-Processor
+FromAnnotations
 (ann
@@ -2688,32 +2688,43 @@
 %3E co
-StatsManualItemProcessor
+OccurringTermsStatsCalculatorManual
 (Ann
@@ -2795,72 +2795,105 @@
   Co
-StatsItemProcessor coStatsItemProcessor = new CoStatsItemProcess
+OccurringTermsStatsCalculator coOccurringTermsStatsCalculator = new CoOccurringTermsStatsCalculat
 or(a
@@ -2941,32 +2941,43 @@
 eturn co
-StatsItemProcess
+OccurringTermsStatsCalculat
 or;%0A    
@@ -3058,29 +3058,40 @@
 %3E co
-StatsAllItemProcessor
+OccurringTermsStatsCalculatorAll
 (Ann
@@ -3162,325 +3162,185 @@
   Co
-StatsItemProcessor coStatsItemProcessor = new CoStatsItemProcessor(%0A                annotationCoTermsAggregatorAll.totalOfAnnotatedGeneProducts(),%0A                annotationCoTermsAggregatorAll.termGPCount(),%0A                annotationCoTermsAggregatorAll.termToTermOverlapMatrix());%0A        return coStatsItemProcess
+OccurringTermsStatsCalculator coOccurringTermsStatsCalculator = new CoOccurringTermsStatsCalculator(annotationCoTermsAggregatorAll);%0A        return coOccurringTermsStatsCalculat
 or;%0A

Rename used classes.