package uk.ac.ebi.spot.goci.curation.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import uk.ac.ebi.spot.goci.model.Gene;
import uk.ac.ebi.spot.goci.model.Locus;
import uk.ac.ebi.spot.goci.model.RiskAllele;
import uk.ac.ebi.spot.goci.model.SingleNucleotidePolymorphism;
import uk.ac.ebi.spot.goci.repository.GeneRepository;
import uk.ac.ebi.spot.goci.repository.LocusRepository;
import uk.ac.ebi.spot.goci.repository.RiskAlleleRepository;
import uk.ac.ebi.spot.goci.repository.SingleNucleotidePolymorphismRepository;

import java.util.ArrayList;
import java.util.Collection;

/**
 * Created by emma on 13/04/2015.
 *
 * @author emma
 *         <p>
 *         Service class that creates the attributes of a loci
 */
@Service
public class LociAttributesService {

    private SingleNucleotidePolymorphismRepository singleNucleotidePolymorphismRepository;
    private GeneRepository geneRepository;
    private RiskAlleleRepository riskAlleleRepository;
    private LocusRepository locusRepository;

    private Logger log = LoggerFactory.getLogger(getClass());

    protected Logger getLog() {
        return log;
    }

    // Constructor
    @Autowired
    public LociAttributesService(SingleNucleotidePolymorphismRepository singleNucleotidePolymorphismRepository,
                                 GeneRepository geneRepository,
                                 RiskAlleleRepository riskAlleleRepository,
                                 LocusRepository locusRepository) {
        this.singleNucleotidePolymorphismRepository = singleNucleotidePolymorphismRepository;
        this.geneRepository = geneRepository;
        this.riskAlleleRepository = riskAlleleRepository;
        this.locusRepository = locusRepository;
    }


    public Collection<Gene> saveGene(Collection<Gene> genes) {
        Collection<Gene> locusGenes = new ArrayList<Gene>();

        genes.forEach(gene -> {
                          // Check if gene already exists, note we may have duplicates so for moment just take first one
                          Gene geneInDatabase = geneRepository.findByGeneName(gene.getGeneName());

                          // Exists in database already
                          if (geneInDatabase != null) {
                              getLog().debug("Gene " + geneInDatabase.getGeneName() + " already exists in database");
                              locusGenes.add(geneInDatabase);
                          }

                          // If gene doesn't exist then create and save
                          else {
                              // Create new gene
                              getLog().debug("Gene " + gene.getGeneName() + " not found in database. Creating and saving new gene.");
                              geneRepository.save(gene);
                              locusGenes.add(gene);
                          }
                      }

        );
        return locusGenes;
    }

    public Collection<Gene> createGene(Collection<String> authorReportedGenes) {
        Collection<Gene> locusGenes = new ArrayList<Gene>();

        authorReportedGenes.forEach(authorReportedGene -> {
            authorReportedGene = tidy_curator_entered_string(authorReportedGene);

            // Check for intergenic
            if (authorReportedGene.equals("Intergenic")) {
                authorReportedGene = authorReportedGene.toLowerCase();
            }

            // Check if gene already exists, note we may have duplicates so for moment just take first one
            Gene geneInDatabase = geneRepository.findByGeneName(authorReportedGene);
            Gene gene;

            // Exists in database already
            if (geneInDatabase != null) {
                getLog().debug("Gene " + geneInDatabase.getGeneName() + " already exists in database");
                gene = geneInDatabase;
            }

            // If gene doesn't exist then create and save
            else {
                // Create new gene
                getLog().debug("Gene " + authorReportedGene + " not found in database. Creating and saving new gene.");
                Gene newGene = new Gene();
                newGene.setGeneName(authorReportedGene);

                // Save gene
                gene = geneRepository.save(newGene);
            }

            // Add genes to collection
            locusGenes.add(gene);
        });
        return locusGenes;
    }


    public Collection<RiskAllele> saveRiskAlleles(Collection<RiskAllele> strongestRiskAlleles) {

        //Create new risk allele, at present we always create a new risk allele for each locus within an association

        Collection<RiskAllele> riskAlleles = new ArrayList<RiskAllele>();

        strongestRiskAlleles.forEach(riskAllele -> {

            // Save SNP
            SingleNucleotidePolymorphism savedSnp = saveSnp(riskAllele.getSnp());
            riskAllele.setSnp(savedSnp);

            // Save proxy SNPs
            Collection<SingleNucleotidePolymorphism> savedProxySnps = new ArrayList<SingleNucleotidePolymorphism>();
            if (!riskAllele.getProxySnps().isEmpty()) {
                riskAllele.getProxySnps().forEach(singleNucleotidePolymorphism -> {
                    savedProxySnps.add(saveSnp(singleNucleotidePolymorphism));
                });
            }
            riskAllele.setProxySnps(savedProxySnps);
            riskAlleleRepository.save(riskAllele);
        });

        return riskAlleles;
    }


    public RiskAllele createRiskAllele(String curatorEnteredRiskAllele, SingleNucleotidePolymorphism snp) {

        //Create new risk allele, at present we always create a new risk allele for each locus within an association
        RiskAllele riskAllele = new RiskAllele();
        riskAllele.setRiskAlleleName(tidy_curator_entered_string(curatorEnteredRiskAllele));
        riskAllele.setSnp(snp);

        // Save risk allele
        riskAlleleRepository.save(riskAllele);
        return riskAllele;
    }

    public void deleteRiskAllele(RiskAllele riskAllele) {
        riskAlleleRepository.delete(riskAllele);
    }

    public void deleteLocus(Locus locus) {
        locusRepository.delete(locus);
    }


    private SingleNucleotidePolymorphism saveSnp(SingleNucleotidePolymorphism snp) {

        // Check if SNP already exists
        SingleNucleotidePolymorphism snpInDatabase =
                singleNucleotidePolymorphismRepository.findByRsIdIgnoreCase(snp.getRsId());

        if (snpInDatabase != null) {
            return snpInDatabase;
        }
        else {
            // save new SNP
            return singleNucleotidePolymorphismRepository.save(snp);
        }
    }


    public SingleNucleotidePolymorphism createSnp(String curatorEnteredSNP) {

        curatorEnteredSNP = tidy_curator_entered_string(curatorEnteredSNP);

        // Check if SNP already exists database
        SingleNucleotidePolymorphism snpInDatabase =
                singleNucleotidePolymorphismRepository.findByRsIdIgnoreCase(curatorEnteredSNP);
        SingleNucleotidePolymorphism snp;
        if (snpInDatabase != null) {
            snp = snpInDatabase;
        }

        // If SNP doesn't exist, create and save
        else {
            // Create new SNP
            SingleNucleotidePolymorphism newSNP = new SingleNucleotidePolymorphism();
            newSNP.setRsId(curatorEnteredSNP);

            // Save SNP
            snp = singleNucleotidePolymorphismRepository.save(newSNP);
        }

        return snp;

    }


    public String tidy_curator_entered_string(String string) {

        String newString = string.trim();
        String newline = System.getProperty("line.separator");

        if (newString.contains(newline)) {
            newString = newString.replace(newline, "");
        }

        return newString;
    }

}

@@ -2069,71 +2069,8 @@
 ists
-, note we may have duplicates so for moment just take first one
 %0A   

Update to comment