/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package motifkmer;

import java.io.IOException;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.Map;
/**
 *
 * @author Rahul Semwal
 */                                          // please see the gtest
public class MotifExtraction 
{

    /**
     *
     * @param CurrentKmer
     * @param BinNumber
     * @param KmerLength
     * @param io
     * @param totalSequence
     * @param frequency
     * @param output
     * @return 
     * @throws java.io.IOException
     */
    public static TreeMap<Double,String> motifTour(KMER CurrentKmer, int BinNumber, int KmerLength, FileIo io,int totalSequence,double frequency[],TreeMap output) throws IOException
    {
        TreeMap<Integer,LinkList<Integer>> Connection = CurrentKmer.getConnection();
        TreeMap<Integer,LinkList<Integer>> updatedIndex=CurrentKmer.getUpdateIndex();
        TreeMap<Integer,LinkList<Integer>> updatedConnection=CurrentKmer.getUpdateConnection();
        LinkList<Integer> updatedPos=null;
        
        DLinkList<String> Sequences = new DLinkList<>();
        DLinkList<LinkNode<Integer>> index = new DLinkList<>();
        DLinkList<LinkNode<Integer>> indexhead = new DLinkList<>();
        
        
        index.addNode(CurrentKmer.getIndex().getHead());
        Sequences.addNode(io.getSequence(BinNumber));
        indexhead.addNode(CurrentKmer.getIndex().getHead());
        
        
        int j=1;
        for(int i : Connection.keySet())
        {
            Sequences.addNode(io.getSequence(i)); // adding corresponding sequence
            index.addNode(Connection.get(i).getHead());    //  adding corresponding linklist
            indexhead.addNode(Connection.get(i).getHead()); // adding corresponding linklist headinfo
           
            
            
            
            if(updatedConnection!=null)
            {
                if(updatedPos==null)
                {
                    updatedPos=new LinkList<>();
                }
                else
                {
                    if(updatedConnection.containsKey(i))
                    {
                        updatedPos.addNode(j);
                    }
                }
            }
            j++;
        
        
        
        }
        
        
        
        DLinkList<LinkNode<Integer>>.DLinkNode<LinkNode<Integer>> indexPtr= index.getHead();
        DLinkList<LinkNode<Integer>>.DLinkNode<LinkNode<Integer>> indexheadPtr = indexhead.getHead();
        DLinkList<LinkNode<Integer>>.DLinkNode<LinkNode<Integer>> setIndexPtr =indexPtr;
        DLinkList<LinkNode<Integer>>.DLinkNode<LinkNode<Integer>> setIndexHeadPtr=indexheadPtr;
        boolean flag=true;
        String seed;
        
        while(flag)
        {
            
            while(indexPtr.getValue() != null)
            {
                int leftgap=0;   // if you want gap=0 in output than in condition put leftgap<1 && rightgap<1
                int rightgap=0;
                String a[]=SACMotif.SeedMotif(Sequences, indexPtr, KmerLength,leftgap,rightgap,totalSequence,frequency).split(",");
                leftgap=Integer.parseInt(a[0]);
                rightgap=Integer.parseInt(a[2]);
                seed=a[1];
                double fitnessScore=Double.valueOf(a[3]);
                double strength=Double.valueOf(a[4]);
                a=null;
                if(leftgap< <"Provide left gap cutoff value"> || rightgap< <"Provide left gap cutoff value">)   
                {
                    int leftint=-1;
                    int rightint=KmerLength;
                    boolean leftflag=true;
                    boolean rightflag=true;
                    double templ=0; 
                    double tempr=0;
                    double leftstrength=0;
                    double rightstrength=0;
                    while((leftflag || rightflag) )
                    {  
                       
                       String b[]=SACMotif.motifElongation(Sequences.getHead(), indexPtr, leftint, rightint, leftflag, rightflag, leftgap, rightgap,totalSequence,frequency).split(",");
                       if((!b[0].isEmpty()) && (!b[1].isEmpty()))
                       {
                           seed= b[0]+"-"+seed+"-"+b[1];
                       }
                       else if((b[0].isEmpty()) && (!b[1].isEmpty()))
                           seed=seed+"-"+b[1];
                       else if((!b[0].isEmpty()) && (b[1].isEmpty()))
                           seed=b[0]+"-"+seed;
                       leftflag=Boolean.valueOf(b[2]);
                       rightflag=Boolean.valueOf(b[3]);
                       leftgap=Integer.parseInt(b[4]);
                       rightgap=Integer.parseInt(b[5]);
                       leftint--;
                       rightint++;
                        if(leftgap==0 && rightgap==0)                           
                       {
                           fitnessScore+=Double.valueOf(b[6])+Double.valueOf(b[7])+templ+tempr;
                           strength+=Double.valueOf(b[8])+Double.valueOf(b[9])+leftstrength+rightstrength;
                           templ=0;
                           tempr=0;
                           leftstrength=0;
                           rightstrength=0;
                           
                       } 
                       else if(leftgap==0 && rightgap!=0)           
                            {
                               fitnessScore+=Double.valueOf(b[6])+templ; 
                               tempr+=Double.valueOf(b[7]);         
                               templ=0;
                               strength+=Double.valueOf(b[8])+leftstrength;
                               rightstrength+=Double.valueOf(b[9]);
                               leftstrength=0;
                            }
                       else if(leftgap!=0 && rightgap==0)     
                            {
                                fitnessScore+=Double.valueOf(b[7])+tempr;
                                templ+=Double.valueOf(b[6]);         
                                tempr=0;
                               strength+=Double.valueOf(b[9])+rightstrength;
                               leftstrength+=Double.valueOf(b[8]);
                               rightstrength=0;
                            }
                       else if(leftgap!=0 && rightgap!=0)
                            {
                                templ+=Double.valueOf(b[6]);         
                                tempr+=Double.valueOf(b[7]);         
                                leftstrength+=Double.valueOf(b[8]);
                                rightstrength+=Double.valueOf(b[9]);
                            }
                       b=null;
                       if(rightgap==<"Provide right gap value">)
                           rightflag=false;
                       if(leftgap==<"Provide Left gap value">)
                           leftflag=false;
                       
                    }
                    seed=seed.substring(leftgap*2,seed.length()-rightgap*2);
                    String m[]=seed.split("-");
                    if(m.length>=2)
                    { output.put(fitnessScore+((strength*1.0D)/m.length), seed);}
                    seed="";
                }
                indexPtr.data = indexPtr.getValue().next;
            }
            
            while((indexPtr.getValue()==null)&&(flag))
            {
                indexPtr.data=indexheadPtr.getValue();
                indexPtr=indexPtr.next;
                indexheadPtr=indexheadPtr.next;
                indexPtr.data=indexPtr.getValue().next;
                if((indexPtr.data==null)&&(indexheadPtr.next==null))
                    flag=false;
            }
            indexPtr=setIndexPtr;
            indexheadPtr=setIndexHeadPtr;
            
        }
        
        
        if(updatedPos!=null)
        {
            updatedPos.reverse();
            indexPtr=setIndexPtr;
            indexheadPtr=setIndexHeadPtr;
            
            
            
            LinkNode<Integer> head =updatedPos.getHead();
            int pos;
            DLinkList<LinkNode<Integer>>.DLinkNode<LinkNode<Integer>> tmpPtr;
            
            Iterator it = updatedIndex.entrySet().iterator();
            while(it.hasNext())
            {
               Map.Entry me = (Map.Entry)it.next();
               pos=head.getValue();
               LinkList<Integer> indexdata=(LinkList<Integer>)me.getValue();
               indexheadPtr.data=indexdata.getHead();
               j=1;
               while(j!=pos)
               {
                   indexheadPtr=indexheadPtr.next;
                   j++;
               }
                tmpPtr=indexheadPtr;
                LinkNode<Integer> tmp= indexheadPtr.getValue();
                indexheadPtr.data=updatedConnection.get((Integer)me.getKey()).getHead();
                flag=true;
                
                
                
                  while(flag)
        {
            
            while(indexPtr.getValue() != null)
            {
                int leftgap=0; // if you want gap=0 in output than in condition put leftgap<1 && rightgap<1
                int rightgap=0;
                String a[]=SACMotif.SeedMotif(Sequences, indexPtr, KmerLength,leftgap,rightgap,totalSequence,frequency).split(",");
                leftgap=Integer.parseInt(a[0]);
                rightgap=Integer.parseInt(a[2]);
                seed=a[1];
                double fitnessScore=Double.valueOf(a[3]);
                double strength=Double.valueOf(a[4]);
                a=null;
               
                if(leftgap< <"Provide Left gap value"> || rightgap< <"Provide right gap value">)
                {
                    int leftint=-1;
                    int rightint=KmerLength;
                    boolean leftflag=true;
                    boolean rightflag=true;
                    double templ=0; 
                    double tempr=0;
                    double leftstrength=0;
                    double rightstrength=0;
                    while((leftflag || rightflag) )
                    {  
                       
                       String b[]=SACMotif.motifElongation(Sequences.getHead(), indexPtr, leftint, rightint, leftflag, rightflag, leftgap, rightgap,totalSequence,frequency).split(",");
                       if((!b[0].isEmpty()) && (!b[1].isEmpty()))
                       {
                           seed= b[0]+"-"+seed+"-"+b[1];
                       }
                       else if((b[0].isEmpty()) && (!b[1].isEmpty()))
                           seed=seed+"-"+b[1];
                       else if((!b[0].isEmpty()) && (b[1].isEmpty()))
                           seed=b[0]+"-"+seed;
                       leftflag=Boolean.valueOf(b[2]);
                       rightflag=Boolean.valueOf(b[3]);
                       leftgap=Integer.parseInt(b[4]);
                       rightgap=Integer.parseInt(b[5]);
                       leftint--;
                       rightint++;
                        if(leftgap==0 && rightgap==0)                         
                       {
                           fitnessScore+=Double.valueOf(b[6])+Double.valueOf(b[7])+templ+tempr;
                           strength+=Double.valueOf(b[8])+Double.valueOf(b[9])+leftstrength+rightstrength;
                           templ=0;
                           tempr=0;
                           leftstrength=0;
                           rightstrength=0;
                           
                       } 
                       else if(leftgap==0 && rightgap!=0)            
                            {
                               fitnessScore+=Double.valueOf(b[6])+templ; 
                               tempr+=Double.valueOf(b[7]);          
                               templ=0;
                               strength+=Double.valueOf(b[8])+leftstrength;
                               rightstrength+=Double.valueOf(b[9]);
                               leftstrength=0;
                            }
                       else if(leftgap!=0 && rightgap==0)     
                            {
                                fitnessScore+=Double.valueOf(b[7])+tempr;
                                templ+=Double.valueOf(b[6]);        
                                tempr=0;
                               strength+=Double.valueOf(b[9])+rightstrength;
                               leftstrength+=Double.valueOf(b[8]);
                               rightstrength=0;
                            }
                       else if(leftgap!=0 && rightgap!=0)
                            {
                                templ+=Double.valueOf(b[6]);         
                                tempr+=Double.valueOf(b[7]);         
                                leftstrength+=Double.valueOf(b[8]);
                                rightstrength+=Double.valueOf(b[9]);
                            }
                       b=null;
                       if(rightgap==<"Provide right gap value">)
                           rightflag=false;
                       if(leftgap==<"Provide left gap value">)
                           leftflag=false;
                       
                    }
                    seed=seed.substring(leftgap*2,seed.length()-rightgap*2);
                    String m[]=seed.split("-");
                    if(m.length>=2)
                    { output.put(fitnessScore+((strength*1.0D)/m.length), seed);}
                    seed="";
                }
                indexPtr.data = indexPtr.getValue().next;
            }
            
            while((indexPtr.getValue()==null)&&(flag))
            {
                indexPtr.data=indexheadPtr.getValue();
                indexPtr=indexPtr.next;
                indexheadPtr=indexheadPtr.next;
                indexPtr.data=indexPtr.getValue().next;
                if((indexPtr.data==null)&&(indexheadPtr.next==null))
                    flag=false;
            }
            indexPtr=setIndexPtr;
            indexheadPtr=setIndexHeadPtr;
            
        }
                

                
                tmpPtr.data=tmp;
                it.remove();
            }
        }
        
        setIndexPtr=null;
        setIndexHeadPtr=null;
        indexPtr=null;
        indexheadPtr=null;
        Sequences.deleteNode();
        index.deleteNode();
        indexhead.deleteNode();  
        CurrentKmer.finalize();
        return(output);
    }
}
