package org.genemania.dw.entity;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.TreeMap;

import org.genemania.dw.db.EnsemblMirrorTables;
import org.genemania.dw.util.DWUtil;
import org.genemania.dw.util.GenUtil;

/**
 * DW view for an Ensembl gene. Encapsulates the attributes of interest
 * for an Ensembl gene from the Ensembl core database.
 * Overriden toString () method represents a displayable entry in the ID
 * mapping tables. Entrez X-refs are included by default.
 * 
 * @author rashadbadrawi
 */

public class EnsemblGene extends ExtResourceGene {
    
    private ArrayList <String> transcriptList = new ArrayList <String> ();
    private ArrayList <String> proteinList = new ArrayList <String> ();
    
    public EnsemblGene () {
    
        setSource(ExtResourceGene.RES_ENSEMBL);
    }

    public static TreeMap <String, ExtResource> loadAllExt (String speciesName)
            throws SQLException {

        TreeMap <String, ExtResource> ensMap =
                          EnsemblMirrorTables.loadAll(speciesName, true);
        
        return ensMap;
    }
    
    public void addTranscriptID (String transID) {
        
        GenUtil.validateString (transID);
        if (!transcriptList.contains (transID)) {
            transcriptList.add (transID);
        }
    }

    public void removeTranscriptID (String transID) {

        GenUtil.validateString(transID);
        if (transcriptList.contains (transID)) {
            transcriptList.remove (transID);
        } else {
            System.out.println ("removeTranscriptID: No such ID: " + transID);
        }
    }
    
    public void addProteinID (String proteinID) {
        
        GenUtil.validateString (proteinID);
        if (!proteinList.contains (proteinID)) {
            proteinList.add (proteinID);
        }
    }

    public void removeProteinID (String proteinID) {

        GenUtil.validateString(proteinID);
        if (proteinList.contains (proteinID)) {
            proteinList.remove (proteinID);
        } else {
            System.out.println ("removeProteinID: No such ID: " + proteinID);
        }
    }
    
    public void addTranscripts (ArrayList <String> transcriptList) {
        
        if (transcriptList == null || transcriptList.size () == 0) {
            throw new IllegalArgumentException ("Invalid transcript list: " + 
                    transcriptList);
        }
        this.transcriptList = transcriptList;
    }
    
    public void addProteins (ArrayList <String> proteinList) {
    
        if (proteinList == null || proteinList.size () == 0) {
            throw new IllegalArgumentException ("Invalid protein list: " + 
                    proteinList);
        }
        this.proteinList = proteinList;    
    }
    
    public ArrayList <String> getTranscripts () { return transcriptList; }
    
    public ArrayList <String> getProteins () { return proteinList; }
    
    @Override
    public String toString () {
        
        String tempStr = getDBID() + "";
        tempStr += GenUtil.TAB;
        
        tempStr += getID();
        tempStr += GenUtil.TAB;
        
        if (TYPE_PROTEIN_CODING_ENSEMBL.equals (getType ())) {
            tempStr += "True";
        } else {
            tempStr += "False";
        }
        tempStr += GenUtil.TAB;
        
        if (getName() != null) {
            tempStr += getName ();
        } else {
            tempStr += GenUtil.NA;
        }
        tempStr += GenUtil.TAB;
        
        tempStr = GenUtil.addList (tempStr, getTranscripts());
        tempStr += GenUtil.TAB;

        tempStr = GenUtil.addList (tempStr, getProteins ());
        tempStr += GenUtil.TAB;
        
        tempStr = GenUtil.addList (tempStr, getUniprotList());
        tempStr += GenUtil.TAB;

        if (DWUtil.SP_MOUSE.equals (speciesName)) {
            tempStr = GenUtil.addList (tempStr, getMGDList());
            tempStr += GenUtil.TAB;
        }

        TreeMap <String, ExtResource> xRefEntrezMap = 
                getXRef (ExtResource.RES_ENTREZ);
        if (xRefEntrezMap == null || xRefEntrezMap.size () == 0) {
            tempStr += GenUtil.NA;
        } else {
            Iterator iterator = xRefEntrezMap.keySet().iterator();
            boolean firstTime = true;
            while (iterator.hasNext ()) {
                if (firstTime) {
                    firstTime = false;
                } else {
                    tempStr += GenUtil.SEMICOLON; 
                }
                String entGeneID = (String)iterator.next ();
                tempStr += entGeneID;
            }
        }
        tempStr += GenUtil.TAB;
        
        tempStr = GenUtil.addList (tempStr, getRefinedXrefList(LIST_REFSEQ_RNA));
        tempStr += GenUtil.TAB;
        
        tempStr = GenUtil.addList (tempStr, getRefinedXrefList(LIST_REFSEQ_PRO));
        tempStr += GenUtil.TAB;
       
        tempStr = GenUtil.addList (tempStr, getRefinedSynList());
        tempStr += GenUtil.TAB;
        
        if (getDefinition() != null) {
            tempStr += getDefinition();
        } else {
            //tempStr = GenUtil.addList (tempStr, getRefinedXrefList(ExtResourceGene.LIST_DEFN));
            tempStr += GenUtil.NA;
        }

        return tempStr;
    }

    public String toStringLeftOver (String xRefType) {

        if (!ExtResourceGene.RES_ENTREZ.equals (xRefType)) {
            throw new IllegalArgumentException ("No support for leftovers for: " +
                    xRefType);
        }
        String tempStr = getDBID() + "";
        tempStr += GenUtil.TAB;

        tempStr += GenUtil.NA;
        tempStr += GenUtil.TAB;

        if (TYPE_PROTEIN_CODING_ENSEMBL.equals (getType ())) {
            tempStr += "True";
        } else {
            tempStr += "False";
        }
        tempStr += GenUtil.TAB;

        if (getName() != null) {
            tempStr += getName ();
        } else {
            tempStr += GenUtil.NA;
        }
        tempStr += GenUtil.TAB;

        tempStr = GenUtil.addList (tempStr, getUniprotList());
        tempStr += GenUtil.TAB;

        if (DWUtil.SP_MOUSE.equals(speciesName)) {
            tempStr = GenUtil.addList (tempStr, getMGDList());
            tempStr += GenUtil.TAB;
        }

        tempStr += getID();
        tempStr += GenUtil.TAB;

        tempStr = GenUtil.addList (tempStr, getRefinedXrefList(LIST_REFSEQ_RNA));
        tempStr += GenUtil.TAB;

        tempStr = GenUtil.addList (tempStr, getRefinedXrefList(LIST_REFSEQ_PRO));
        tempStr += GenUtil.TAB;

        tempStr = GenUtil.addList (tempStr, getRefinedSynList());
        tempStr += GenUtil.TAB;

        if (getDefinition() != null) {
            tempStr += getDefinition();
        } else {
            tempStr += GenUtil.NA;
        }

        return tempStr;
    }
}
