package org.intermine.bio.dataconversion;

/*
 * Copyright (C) 2002-2011 FlyMine
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  See the LICENSE file for more
 * information or http://www.gnu.org/copyleft/lesser.html.
 *
 */

import java.io.Reader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.intermine.dataconversion.ItemWriter;
import org.intermine.metadata.Model;
import org.intermine.util.FormattedTextParser;
import org.intermine.xml.full.Attribute;
import org.intermine.xml.full.Item;


/**
 * Read RGD RAT_GENES identifiers file to create canonical rat genes with correct identifiers.
 * @author Richard Smith
 */
public class RgdIdentifiersConverter extends BioFileConverter
{
    //
    private static final String DATASET_TITLE = "RGD gene identifiers";
    private static final String DATA_SOURCE_NAME = "Rat Genome Database";

    private static final String RAT_TAXON = "10116";

    protected static final Logger LOG = Logger.getLogger(RgdIdentifiersConverter.class);

    /**
     * Constructor
     * @param writer the ItemWriter used to handle the resultant items
     * @param model the Model
     */
    public RgdIdentifiersConverter(ItemWriter writer, Model model) {
        super(writer, model, DATA_SOURCE_NAME, DATASET_TITLE);
    }

    /**
     *
     *
     * {@inheritDoc}
     */
    public void process(Reader reader) throws Exception {

        Set<String> seenEnsembls = new HashSet<String>();
        Set<String> duplicateEnsembls = new HashSet<String>();
        Map<String, Integer> storedGeneIds = new HashMap<String, Integer>();
        Map<String, String> geneEnsemblIds = new HashMap<String, String>();

        // Read all lines into id pairs, track any ensembl ids or symbols that appear twice
        Iterator lineIter = FormattedTextParser.parseTabDelimitedReader(reader);

        // remove header line
        // check symbol and ncbiGeneNumber unique

        while (lineIter.hasNext()) {
            String[] line = (String[]) lineIter.next();

            if (line[0].startsWith("GENE_RGD_ID")) {
                continue;
            }
            String rgdId = line[0];
            String symbol = line[1];
            String name = line[2];
            String description = line[3];
            String entrez = line[20];
            String ensembl = line[37];

            Item gene = createItem("Gene");
            gene.setReference("organism", getOrganism(RAT_TAXON));
            gene.setAttribute("secondaryIdentifier", "RGD:" + rgdId);
            gene.setAttribute("symbol", symbol);

            Set<String> ensemblIds = parseEnsemblIds(ensembl);
            for (String ensemblId : ensemblIds) {
                if (seenEnsembls.contains(ensemblId)) {
                    duplicateEnsembls.add(ensemblId);
                } else {
                    seenEnsembls.add(ensemblId);
                }
            }
            // if there was exactly one ensemblId we may be able to set primaryIdentifier
            if (ensemblIds.size() == 1) {
                geneEnsemblIds.put(gene.getIdentifier(), ensemblIds.iterator().next());
            } else {
                // if more than one we have to create synonyms
                for (String ensemblId : ensemblIds) {
                    createSynonym(gene.getIdentifier(), ensemblId, true);
                }
            }

            if (!StringUtils.isBlank(name)) {
                gene.setAttribute("name", name);
            }
            if (!StringUtils.isBlank(description)) {
                gene.setAttribute("description", description);
            }
            if (!StringUtils.isBlank(entrez)) {
                gene.setAttribute("ncbiGeneNumber", entrez);
            }

            Integer storedGeneId = store(gene);
            storedGeneIds.put(gene.getIdentifier(), storedGeneId);
        }

        LOG.info("ENSEMBL: duplicateEnsemblIds.size() = " + duplicateEnsembls.size());
        LOG.info("ENSEMBL: duplicateEnsemblIds = " + duplicateEnsembls);
        // now check that we only saw each ensembl id once
        for (Map.Entry<String, String> entry : geneEnsemblIds.entrySet()) {
            String geneIdentifier = entry.getKey();
            String ensemblId = entry.getValue();
            if (!duplicateEnsembls.contains(ensemblId)) {
                Attribute att = new Attribute("primaryIdentifier", ensemblId);
                store(att, storedGeneIds.get(geneIdentifier));
            }
        }
    }

    private Set<String> parseEnsemblIds(String fromFile) {
        Set<String> ensembls = new HashSet<String>();
        if (!StringUtils.isBlank(fromFile)) {
            ensembls.addAll(Arrays.asList(fromFile.split(";")));
        }
        return ensembls;
    }
}

@@ -1672,66 +1672,9 @@
  %7B%0A%0A
-        Set%3CString%3E seenEnsembls = new HashSet%3CString%3E();
 %0A
+
     
@@ -2702,14 +2702,12 @@
 te(%22
-second
+prim
 aryI
@@ -2918,631 +2918,71 @@
     
-if (seenEnsembls.contains(ensemblId)) %7B%0A                    duplicateEnsembls.add(ensemblId);%0A                %7D else %7B%0A                    seenEnsembls.add(ensemblId);%0A                %7D%0A            %7D%0A            // if there was exactly one ensemblId we may be able to set primaryIdentifier%0A            if (ensemblIds.size() == 1) %7B%0A                geneEnsemblIds.put(gene.getIdentifier(), ensemblIds.iterator().next());%0A            %7D else %7B%0A                // if more than one we have to create synonyms%0A                for (String ensemblId : ensemblIds) %7B%0A                    createSynonym(gene.getIdentifier(), e
+createCrossReference(gene.getIdentifier(), ensemblId, %22E
 nsembl
-Id
+%22
 , tr
@@ -2990,26 +2990,8 @@
 e);%0A
-                %7D%0A
     
@@ -3284,24 +3284,24 @@
 (entrez)) %7B%0A
-
             
@@ -3349,16 +3349,98 @@
 ntrez);%0A
+                createCrossReference(gene.getIdentifier(), entrez, %22NCBI%22, true);%0A
         

move ensembl to xrefs, use RGD ID as primary identifier