package taskspaces.rna;

import java.util.*;

/**
 * Class Matcher contains methods to match Strings
 * using the BM (Boyer-Moore) class and Java methods.
 * @author      Robert Markel 
 * @version     1.00 29 August 2002 
 */
public class Matcher 
{ 
   /** 
   * Finds a given pattern in a 
   * given text using a Boyer-Moore search.
   * @param pattern the pattern to search for. 
   * @param text the text to search. 
   * @return <code>true</code> if the pattern was found, otherwise <code>false</code>. 
   */
   public static boolean matchBM(String pattern,String text)
   {
      boolean found=false;
      int index=0;
      BM boyerMoore=new BM();
      boyerMoore.compile(pattern);
      byte[] textBytes=text.getBytes();
      while((index=boyerMoore.search(textBytes,index,textBytes.length-index))>=0)
      {
         if(index>=0) return true;
      }
      return false;
   }

   /**
   * Finds a given pattern in a
   * given text at a given index using a Boyer-Moore search.
   * @param pattern the pattern to search for.
   * @param text the text to search.
   * @return <code>true</code> if the pattern was found at the specified index.
   */
   public static boolean matchBM(String pattern,String text,int indx)
   {
      int index=0;
      BM boyerMoore=new BM();
      boyerMoore.compile(pattern);
      byte[] textBytes=text.getBytes();
      while((index=boyerMoore.search(textBytes,index,textBytes.length-index))>=0)
      {
         if(index>=0)
         {
            if(index==indx) return true;
            index+=pattern.length();
            continue;
         }
      }
      return false;
   }

   /** 
   * Finds a given set of patterns in a 
   * given text using a Boyer-Moore search.
   * @param pattern the pattern to search for. 
   * @param text the text to search. 
   * @return <code>true</code> if all patterns were found, <code>false</code> otherwise. 
   */
   public static boolean matchBM(String[] patterns,String text)
   {
      boolean found=false;
      BM boyerMoore=new BM();
      int patternNumber=patterns.length;
      byte[] textBytes=text.getBytes();
      for(int i=0; i<patternNumber; i++)
      {
         boyerMoore.compile(patterns[i]);
         int index=0;
         while((index=boyerMoore.search(textBytes,index,textBytes.length-index))>=0)
         {
            if(index>=0)
            {
               if(i==patternNumber-1)
               {
                  found=true;
                  break;
               }
               index+=patterns[i].length();
               continue;
            }
         }
      }
      return found;
   }

   /**
   * Finds a given set of patterns in a
   * given text at specific indices using a Boyer-Moore search.
   * This code assumes the patterns will match indices in the text 
   * in ascending order.
   * @param pattern the pattern to search for.
   * @param text the text to search.
   * @param indices indices where matches should occur.
   * @return <code>true</code> if all patterns were found, <code>false</code> otherwise.
   */
   public static boolean matchBM(String[] patterns,String text,int[] indices)
   {
      BM boyerMoore=new BM();
      int patternNumber=patterns.length;
      byte[] textBytes=text.getBytes();
      int patternsFound=0;
      for(int i=0; i<patterns.length; i++)
      {
         boyerMoore.compile(patterns[i]);
         int index=0;
         while((index=boyerMoore.search(textBytes,index,textBytes.length-index))>=0)
         {
            if(index>=0)
            {
               if(index==indices[i]) patternsFound++; 
               if(patternsFound==patternNumber) return true;
               index+=patterns[i].length();
               continue;
            }
         }
      }
      return false;
   }

   /**
   * Finds a given set of patterns in a
   * given text at specified indices meeting specified constraints.
   * This code assumes the patterns will match indices in ascending order.
   * @param pattern the pattern to search for.
   * @param text the text to search.
   * @param indices indices where matches should occur.
   * @param constraints list of constraint integer arrays.
   * @return <code>true</code> if all patterns were found, <code>false</code> otherwise.
   */
   public static boolean match(String[] patterns,String text,int[] indices,List constraints) throws Exception
   {
      int textLength=text.length();
      for(int i=0; i<patterns.length; i++)
      {
         String pattern=patterns[i];
         int index=indices[i];
         int patternLength=pattern.length();
         /*
         if(textLength<index+patternLength)
         {
            return false;
         }
         */
         if(textLength<index+patternLength) return false;

         String s=text.substring(index,index+patternLength);
          /*
         if(!pattern.equals(s)) 
         { 
            return false;
         }
         */
         if(!pattern.equals(s)) return false;

         /*
         System.out.println("0structure: "+pattern);
         System.out.println("1structure: "+s);
         System.out.println();
         */
      }
      HashMap pairs=PairList.getPairMap(text); 
      for(int i=0; i<constraints.size(); i++)
      {
        int[] constraint=(int[])constraints.get(i);
        int firstModuleInsertionPoint=indices[constraint[1]];
        int secondModuleInsertionPoint=indices[constraint[3]];
        for(int j=0; j<constraint[0]; j++)
        {
           int firstBaseIndex=constraint[2]+firstModuleInsertionPoint+j;
           //int secondBaseIndex=constraint[4]+secondModuleInsertionPoint+constraint[0]-j;
           int secondBaseIndex=constraint[4]+secondModuleInsertionPoint+constraint[0]-j-1;
           int pairedBaseIndex;
           try
           {
              pairedBaseIndex=((Integer)pairs.get(new Integer(firstBaseIndex))).intValue();
           } 
           catch(NullPointerException e) 
           { 
              return false; 
           }
           /*
           if(secondBaseIndex!=pairedBaseIndex) 
           {
              return false;
           }
           */
           if(secondBaseIndex!=pairedBaseIndex) return false;
        }
      }
      return true;
   }

   /**
   * Finds a given set of patterns in a
   * given text at specified indices.
   * This code assumes the patterns will match indices in ascending order.
   * @param pattern the pattern to search for.
   * @param text the text to search.
   * @param indices indices where matches should occur.
   * @return <code>true</code> if all patterns were found, <code>false</code> otherwise.
   */
   public static boolean match(String[] patterns,String text,int[] indices) throws Exception
   {
      int textLength=text.length();
      for(int i=0; i<patterns.length; i++)
      {
         String pattern=patterns[i];
         int index=indices[i];
         int patternLength=pattern.length();
         if(textLength<index+patternLength) return false;
         String s=text.substring(index,index+patternLength);
         if(!pattern.equals(s)) return false;
      }
      return true;
   }

   /**
   * Finds a patterns in a text at a specified index.
   * @param pattern the pattern to search for.
   * @param text the text to search.
   * @param index index where match should occur.
   * @return <code>true</code> if pattern was found, <code>false</code> otherwise.
   */
   public static boolean match(String pattern,String text,int index) throws Exception
   {
      int t=text.length();
      int p=pattern.length();
      if(t<index+p) return false;
      String s=text.substring(index,index+p);
      if(pattern.equals(s)) return true;
      return false;
   }
}
