//
// This software is now distributed according to
// the Lesser Gnu Public License.  Please see
// http://www.gnu.org/copyleft/lesser.txt for
// the details.
//    -- Happy Computing!
//
package com.stevesoft.pat.wrap;

import jalview.util.MessageManager;

import java.io.IOException;
import java.io.RandomAccessFile;

import com.stevesoft.pat.BasicStringBufferLike;
import com.stevesoft.pat.Regex;
import com.stevesoft.pat.StringLike;

/**
 * Provides a wrapper for a RandomAccessFile so that it can be searched by
 * Regex.
 */
public class RandomAccessFileWrap implements StringLike
{

  long offset = 0;

  public void setOffset(long o)
  {
    offset = o;
    i0 = iend = 0;
  }

  public long getOffset()
  {
    return offset;
  }

  RandomAccessFile raf;

  int i0 = 0, iend = 0;

  byte[] buf = new byte[1024];

  public int getBufferSize()
  {
    return buf.length;
  }

  public void setBufferSize(int bs)
  {
    buf = new byte[bs];
    i0 = iend = 0;
  }

  public RandomAccessFileWrap(String file) throws IOException
  {
    this.raf = new RandomAccessFile(file, "r");
  }

  public RandomAccessFileWrap(RandomAccessFile raf)
  {
    this.raf = raf;
  }

  @Override
  public char charAt(int i)
  {
    if (i >= i0 && i < iend)
    {
      return (char) buf[i - i0];
    }

    try
    {
      i0 = i - 5;
      // if(i0+offset<0) i0=(int)(-offset);
      if (i0 < 0)
      {
        i0 = 0;
      }
      raf.seek(i0 + offset);
      iend = i0 + raf.read(buf, 0, buf.length);

      if (i >= i0 && i < iend)
      {
        return (char) buf[i - i0];
      }
    } catch (Throwable t)
    {
    }

    throw new ArrayIndexOutOfBoundsException(MessageManager
            .formatMessage("exception.out_of_bounds_for_file", new String[]
            { Integer.valueOf(i).toString(), Integer.valueOf(i0).toString(),
                Integer.valueOf(iend).toString() }));
  }

  @Override
  public String toString()
  {
    throw new Error(MessageManager.getString("error.not_implemented"));
  }

  @Override
  public int length()
  {
    try
    {
      long len = raf.length() - offset;
      if (len > Integer.MAX_VALUE)
      {
        return Integer.MAX_VALUE;
      }
      return (int) len;
    } catch (IOException ioe)
    {
      return 0;
    }
  }

  @Override
  public String substring(int i1, int i2)
  {
    StringBuffer sb = new StringBuffer();
    for (int i = i1; i < i2; i++)
    {
      sb.append(charAt(i));
    }
    return sb.toString();
  }

  @Override
  public Object unwrap()
  {
    return raf;
  }

  /**
   * @j2sIgnore
   * 
   * @param files
   * @throws IOException
   */
  public static void main(String[] files) throws IOException
  {
    for (int i = 0; i < files.length; i++)
    {
      RandomAccessFileWrap fw = new RandomAccessFileWrap(
              new RandomAccessFile(files[i], "r"));
      Regex r = new Regex("toString\\(\\) *(?@{})");
      r.setGFlag(true);
      r.optimize();
      System.out.print(files[i] + " ");
      int j = 0;
      do
      {
        if (r.searchFrom(fw, j))
        {
          System.out.println("Matched at index: " + r.matchedFrom());
          j = r.matchedTo();
        }
        else
        {
          System.out.println("not found");
        }
        System.out.println(r.stringMatched());
      } while (r.didMatch());
    }
  }

  @Override
  public BasicStringBufferLike newStringBufferLike()
  {
    return new StringBufferWrap();
  }

  @Override
  public int indexOf(char c)
  {
    for (int i = 0; i < length(); i++)
    {
      if (charAt(i) == c)
      {
        return i;
      }
    }
    return -1;
  }
}
