package ch.difty.scipamato.core.sync.launcher;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

/**
 * Launcher for the reference dat sync job. Comprises of the following synchronization jobs:
 * <ol>
 * <li> code_class </li>
 * <li> codes </li>
 * <li> keywords TODO </li>
 * <li> papers</li>
 * </ol>
 * @author u.joss
 */
@Slf4j
@Component
public class RefDataSyncJobLauncher implements SyncJobLauncher {

    @Autowired
    @Qualifier("syncCodeClassJob")
    private Job syncCodeClassJob;

    @Autowired
    @Qualifier("syncCodeJob")
    private Job syncCodeJob;

    @Autowired
    @Qualifier("syncPaperJob")
    private Job syncPaperJob;

    @Autowired
    protected JobLauncher jobLauncher;

    @Override
    public SyncJobResult launch() {
        log.info("Starting synchronization job from scipamato-core to scipamato-public...");
        final SyncJobResult result = new SyncJobResult();
        final JobParameters jobParameters = new JobParametersBuilder().addDate("runDate", Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()), true).toJobParameters();
        try {
            runSingleJob("code_classes", syncCodeClassJob, result, jobParameters);
            runSingleJob("codes", syncCodeJob, result, jobParameters);
            runSingleJob("papers", syncPaperJob, result, jobParameters);
            log.info("Job finished successfully.");
        } catch (final Exception ex) {
            log.error("Job terminated.", ex);
            result.setFailure("Unexpected exception of type " + ex.getClass() + ": " + ex.getMessage());
        }
        return result;
    }

    private void runSingleJob(final String topic, final Job job, final SyncJobResult result, final JobParameters jobParameters)
            throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, JobParametersInvalidException {
        setResultFrom(jobLauncher.run(job, jobParameters), result, topic);
    }

    private void setResultFrom(final JobExecution jobExecution, final SyncJobResult result, final String topic) {
        final Long id = jobExecution.getId();
        final String exitCode = jobExecution.getExitStatus().getExitCode();
        final String status = jobExecution.getStatus().name();
        final int writeCount = jobExecution.getStepExecutions().stream().mapToInt(StepExecution::getWriteCount).sum();
        final String msg = String.format("Job %d has returned with exitCode %s (status %s): %d %s were synchronized.", id, exitCode, status, writeCount, topic);

        setMessageToResult(result, msg, jobExecution.getStatus());
    }

    private void setMessageToResult(final SyncJobResult result, final String msg, final BatchStatus status) {
        if (status == BatchStatus.COMPLETED)
            result.setSuccess(msg);
        else
            result.setFailure(msg);
    }

}
@@ -807,71 +807,8 @@
 on;%0A
-import org.springframework.beans.factory.annotation.Autowired;%0A
 impo
@@ -1272,35 +1272,26 @@
     
-@Autowired%0A    @Qualifier(%22
+private final Job 
 sync
@@ -1302,18 +1302,17 @@
 ClassJob
-%22)
+;
 %0A    pri
@@ -1308,32 +1308,38 @@
 ob;%0A    private 
+final 
 Job syncCodeClas
@@ -1338,75 +1338,250 @@
 Code
-Class
+Job;%0A    private final Job syncPaper
 Job;%0A
-%0A
     
-@Autowired%0A    @Qualifier(%22syncCodeJob%22)%0A    private
+protected final JobLauncher jobLauncher;%0A%0A    public RefDataSyncJobLauncher(final JobLauncher jobLauncher, @Qualifier(%22syncCodeClassJob%22) final Job syncCodeClassJob, @Qualifier(%22syncCodeJob%22) final
  Job
@@ -1592,38 +1592,30 @@
 cCodeJob
-;%0A
+,
 %0A    
-@Autowired%0A
+   
     
+ 
 @Qualifi
@@ -1632,28 +1632,22 @@
 perJob%22)
-%0A    private
+ final
  Job syn
@@ -1659,64 +1659,189 @@
 rJob
-;%0A
+) %7B
 %0A    
-@Autowired%0A    protected JobLauncher jobLauncher;
+    this.jobLauncher = jobLauncher;%0A        this.syncCodeClassJob = syncCodeClassJob;%0A        this.syncCodeJob = syncCodeJob;%0A        this.syncPaperJob = syncPaperJob;%0A    %7D
 %0A%0A  

Refactor RefDataSyncJobLauncher