package hep.io.root.reps;

import hep.io.root.core.AbstractRootObject;
import hep.io.root.core.RootInput;
import hep.io.root.interfaces.TBranch;
import hep.io.root.interfaces.TLeafC;
import hep.io.root.interfaces.TLeafI;

import java.io.IOException;

import org.apache.bcel.Constants;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.Type;


/**
 * @author Tony Johnson
 * @version $Id: TLeafCRep.java,v 1.4 2004/06/28 15:21:24 tonyj Exp $
 */
public abstract class TLeafCRep extends AbstractRootObject implements TLeafC, Constants
{
   private Object lastValue;
   private String lastString;
   private TBranch branch;
   private int lastStringIndex;
   private int lastValueIndex;

   public void setBranch(TBranch branch)
   {
      this.branch = branch;
      lastValueIndex = -1;
      lastStringIndex = -1;
   }

   public String getValue(int index) throws IOException
   {
      try
      {
         if (index == lastStringIndex)
            return lastString;

         RootInput in = branch.setPosition(this, lastStringIndex = index);
         return lastString = in.readString();
      }
      catch (IOException x)
      {
         lastStringIndex = -1;
         throw x;
      }
   }

   public Object getWrappedValue(int index) throws IOException
   {
      try
      {
         if (lastValueIndex == index)
            return lastValue;
         lastValueIndex = index;

         RootInput in = branch.setPosition(this, index);
         int arrayDim = getArrayDim();
         if (arrayDim == 0)
            return lastValue = in.readString();
         else if (arrayDim == 1)
         {
            TLeafI count = (TLeafI) getLeafCount();
            int len = (count == null) ? getLen() : count.getValue(index);
            String[] array = new String[len];
            for (int i = 0; i < len; i++)
               array[i] = in.readString();
            return lastValue = array;
         }
         else
         {
            return lastValue = readMultiArray(in, RepConstants.stringClass, index);
         }
      }
      catch (IOException x)
      {
         lastValueIndex = -1;
         throw x;
      }
   }

   public void generateReadCode(InstructionList il, InstructionFactory factory, ConstantPoolGen cp, String className)
   {
      String leafClassName = getClass().getName();
      int arrayDim = getArrayDim();
      if (arrayDim == 0)
         il.append(factory.createInvoke(leafClassName, "getValue", Type.STRING, new Type[]
               {
                  Type.INT
               }, INVOKEVIRTUAL));
      else
         il.append(factory.createInvoke(leafClassName, "getWrappedValue", Type.OBJECT, new Type[]
               {
                  Type.INT
               }, INVOKEVIRTUAL));
   }

   abstract Object[] readMultiArray(RootInput in, Class type, int index);
}
