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.UniprotMirrorTables;
import org.genemania.dw.util.GenUtil;

/**
 * A representation for a Uniprot protein. Currently focused on Uniprot
 * ID mapping service. Each instance of this class represents one accession.
 *
 * GI, RefSeq are an exception in the sense they are not set from their primary
 * resource object (i.e. Entrez).
 *
 * @author rashadbadrawi
 */

public class Uniprot extends ExtResource {

    private int speciesID;
    private ArrayList <String> refSeqProList = new ArrayList <String> ();
    private ArrayList <String> GIList = new ArrayList <String> ();

    public Uniprot () {

        setSource(ExtResource.RES_UNIPROT);
    }

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

        TreeMap <String, ExtResource> uniMap =
                                        UniprotMirrorTables.loadAll(speciesID);

        return uniMap;
    }

    public static TreeMap <String, ExtResource> mapToXref (String xrefType,
                                   String xrefID) throws SQLException {

        TreeMap <String, ExtResource> uniMap =
                               UniprotMirrorTables.maptoXref(xrefType, xrefID);

        return uniMap;
    }

    public void setSpeciesID (int speciesID) {

        GenUtil.validateNonNegativeInt(speciesID);
        this.speciesID = speciesID;
    }

    public void addGI (String GI) {

        GenUtil.validateString (GI);
        if (!GIList.contains (GI)) {
            GIList.add (GI);
        }
    }

    public void removeGI (String GI) {

        GenUtil.validateString(GI);
        if (GIList.contains (GI)) {
            GIList.remove (GI);
        } else {
            System.out.println ("GI ID: No such ID: " + GI);
        }
    }

    public void addRefSeqProID (String refSeqProID) {

        GenUtil.validateString (refSeqProID);
        if (!refSeqProList.contains (refSeqProID)) {
            refSeqProList.add (refSeqProID);
        }
    }

    public void removeRefSeqProID (String refSeqProID) {

        GenUtil.validateString(refSeqProID);
        if (refSeqProList.contains (refSeqProID)) {
            refSeqProList.remove (refSeqProID);
        } else {
            System.out.println ("removeRefSeqProID: No such ID: " + refSeqProID);
        }
    }

    public int getSpeciesID () { return speciesID; }
    
    public ArrayList <String> getRefSeqProList () { return refSeqProList; }

    public ArrayList <String> getGIList () { return GIList; }

    @Override
    public String toString () {

        String tempStr = getSpeciesID() + "";
        tempStr += GenUtil.TAB;

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

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

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

        TreeMap <String, ExtResource> xRefEnsemblMap =
                getXRef (ExtResource.RES_ENSEMBL);
        if (xRefEnsemblMap == null || xRefEnsemblMap.size () == 0) {
            tempStr += GenUtil.NA;
        } else {
            Iterator iterator = xRefEnsemblMap.keySet().iterator();
            boolean firstTime = true;
            while (iterator.hasNext ()) {
                String ensGeneID = (String)iterator.next ();
                tempStr += ensGeneID;
                if (firstTime) {
                    firstTime = false;
                } else {
                    tempStr += GenUtil.SEMICOLON;
                }
            }
        }
        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 ()) {
                String ensGeneID = (String)iterator.next ();
                tempStr += ensGeneID;
                if (firstTime) {
                    firstTime = false;
                } else {
                    tempStr += GenUtil.SEMICOLON;
                }
            }
        }
        tempStr += GenUtil.TAB;

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

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

        return tempStr;
    }
}
