/*
 *This library is free software; you can redistribute it and/or
 *modify it under the terms of the GNU Lesser General Public
 *License as published by the Free Software Foundation; either
 *version 2.1 of the License, or (at your option) any later version.
 *
 *This library is distributed in the hope that it will be useful,
 *but WITHOUT ANY WARRANTY; without even the implied warranty of
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *Lesser General Public License for more details.
 *
 *You should have received a copy of the GNU Lesser General Public
 *License along with this library; if not, write to the Free Software
 *Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/* 
 * This software was written by Phillip Lord (p.lord@hgmp.mrc.ac.uk)
 * whilst at the University of Manchester as a Pfizer post-doctoral 
 * Research Fellow. 
 *
 * The initial code base is copyright by Pfizer, or the University
 * of Manchester. Modifications to the initial code base are copyright
 * of their respective authors, or their employers as appropriate. 
 * Authorship of the modifications may be determined from the ChangeLog
 * placed at the end of this file
 */

package uk.ac.man.bioinf.sequence.complex; // Package name inserted by JPack
import uk.ac.man.bioinf.sequence.AbstractMutableSequence;
import uk.ac.man.bioinf.sequence.AbstractSequence;
import uk.ac.man.bioinf.sequence.DefaultSequence;
import uk.ac.man.bioinf.sequence.EditableSequence;
import uk.ac.man.bioinf.sequence.Element;
import uk.ac.man.bioinf.sequence.InvalidSequenceTypeException;
import uk.ac.man.bioinf.sequence.Residue;
import uk.ac.man.bioinf.sequence.Sequence;
import uk.ac.man.bioinf.sequence.SequenceType;
import uk.ac.man.bioinf.sequence.Sequences;
import uk.ac.man.bioinf.sequence.alignment.AbstractGappedSequence;
import uk.ac.man.bioinf.sequence.alignment.DefaultGappedSequence;
import uk.ac.man.bioinf.sequence.alignment.Gap;
import uk.ac.man.bioinf.sequence.alignment.GappedSequence;
import uk.ac.man.bioinf.sequence.event.SequenceListener;
import uk.ac.man.bioinf.sequence.event.SequenceVetoException;
import uk.ac.man.bioinf.sequence.event.VetoableSequenceListener;
import uk.ac.man.bioinf.sequence.identifier.Identifier;
import uk.ac.man.bioinf.util.IntArrayList;


/**
 * DefaultGappedComplexSequence.java
 *
 *
 * Created: Tue Dec  5 16:55:11 2000
 *
 * @author Phillip Lord
 * @version $Id: DefaultGappedComplexSequence.java,v 1.2 2001/04/11 17:04:43 lord Exp $
 */

public class DefaultGappedComplexSequence extends AbstractComplexSequence
  implements GappedComplexSequence
{

  // This carries contains the Gap model that we are using, and
  // provides access to the GappedSequence model
  private DisabledDefaultGappedSequence gappedSequence;
  
  // this element array contains the complex elements. Its also the
  // underlying data structure (as an Element array) for the ungapped
  // sequences elements in the DefaultGappedComplexSequence. 
  private ComplexElement[] elements;

  public DefaultGappedComplexSequence( Element[] elements, ComplexSequenceType type )
  {
    super( type );
   
    IntArrayList list = DefaultGappedSequence.getGapModelForElements( elements );
    
    Sequences.printElements( elements );
    System.out.println( list.get( list.size() - 1 ) );
    
    Residue[] strippedElements = DefaultGappedSequence.stripGapsFromElements
      ( elements, list.get( 0 ) );
    
    ComplexElement[] strippedComplexElements = Sequences.getResiduesAsComplexElements( strippedElements );
    
    this.elements = strippedComplexElements;
    
    
    DefaultSequence sequence = new DefaultSequence( strippedComplexElements, null ){
	public void checkSequenceType( Element[] elems ) throws InvalidSequenceTypeException
	{
	  // no implementation okay
	}
      };
    
    gappedSequence = new DisabledDefaultGappedSequence
      ( sequence, list );
  }

  public ComplexElement getComplexElementAt( int index )
  {
    return (ComplexElement)gappedSequence.getElementAt( index );
  }
  
  public Element getElementAt( int index ) 
  {
    return getComplexElementAt( index ).getResidue();
  }
  
  public Element getGappedElementAt( int index ) 
  {
    int ungappedIndex = gappedSequence.getUngappedPositionOf( index );
    
    if( ungappedIndex < 1 ){
      return Gap.GAP;
    }
    
    return getElementAt( ungappedIndex );
  }
  
  public ComplexElement[] getSequenceAsComplexElements()
  {
    // this is returning an array which actually contains
    // ComplexElements
    Element[] elems = gappedSequence.getSequenceAsElements();
    
    ComplexElement[] complexElems = new ComplexElement[ elems.length ];
    
    System.arraycopy( elems, 0, complexElems, 0, elems.length );
    return complexElems;
  }
  
  protected ComplexElement setElementAtQuietly( ComplexElement elem, int index )
  {
    checkComplexSequenceType( elem );
    elements[ index - 1 ] =  elem;
    return elem;
  }
  
  public Identifier getIdentifier() {
    // (PENDING:- PL) write this. 
    return gappedSequence.getIdentifier();
  }
  
  

  
  /**
   * This class provides us with the data model for holding all of the
   * elements, and means that we can reuse the GapModel of the
   * GappedSequence implementation. One problem is that the
   * SequenceType of the super class gets in the way. We want to store
   * ComplexElements which are not part of the sequence type. So we
   * need to disable the type checking mechanism. 
   *
   * We also need to ensure that the event mechanism is not to
   * wasteful, and disable most of this as well
   *
   */
  class DisabledDefaultGappedSequence extends DefaultGappedSequence
  {
    DisabledDefaultGappedSequence( Sequence seq, IntArrayList toGappedMap )
    {
      super( seq, toGappedMap );
    }
    
    protected void checkSequenceType( Element element ) throws InvalidSequenceTypeException
    {
      //empty definition okay!
    }
    
    protected void checkSequenceType( Element[] elements ) throws InvalidSequenceTypeException
    {
      //empty definition okay
    }
  }

  // Code for delegation of uk.ac.man.bioinf.sequence.alignment.DefaultGappedSequence methods to gappedSequence
  public GappedSequence getElementsAsGappedSequence(Element[] param1, SequenceType param2, Identifier param3) {
    return gappedSequence.getElementsAsGappedSequence(param1, param2, param3);
  }
  
  public GappedSequence getElementsAsGappedSequence(Element[] param1, SequenceType param2) {
    return gappedSequence.getElementsAsGappedSequence(param1, param2);
  }
  
  public Element[] getSequenceAsElements() {
    return gappedSequence.getSequenceAsElements();
  }

  public int getLength() {
    return gappedSequence.getLength();
  }

  public GappedSequence getGappedSubSequence(int param1, int param2) {
    return gappedSequence.getGappedSubSequence(param1, param2);
  }

  
  public Element[] getGappedSequenceAsElements() {
    return gappedSequence.getGappedSequenceAsElements();
  }
  
  public int getGappedLength() {
    return gappedSequence.getGappedLength();
  }
  
  public int getGappedPositionOf(int param1) {
    return gappedSequence.getGappedPositionOf(param1);
  }
  
  public int getUngappedPositionOf(int param1) {
    return gappedSequence.getUngappedPositionOf(param1);
  }
  // Code for delegation of uk.ac.man.bioinf.sequence.alignment.AbstractGappedSequence methods to gappedSequence
  
  public void insertGapAt(int param1) throws SequenceVetoException {
    gappedSequence.insertGapAt(param1);
  }
  
  public void insertGapAt(int param1, int param2) throws SequenceVetoException {
    gappedSequence.insertGapAt(param1, param2);
  }
  
  public void deleteGapAt(int param1) throws SequenceVetoException {
    gappedSequence.deleteGapAt(param1);
  }

  public void deleteGapAt(int param1, int param2) throws SequenceVetoException {
    gappedSequence.deleteGapAt(param1, param2);
  }
  
  public char getGappedElementAtAsChar(int param1) {
    return gappedSequence.getGappedElementAtAsChar(param1);
  }
  
  public char[] getGappedSequenceAsChars() {
    return gappedSequence.getGappedSequenceAsChars();
  }

  // Code for delegation of uk.ac.man.bioinf.sequence.AbstractSequence methods to gappedSequence
  public Sequence getSubSequence(int param1, int param2) {
    return gappedSequence.getSubSequence(param1, param2);
  }
  
  public char[] getSequenceAsChars() {
    return gappedSequence.getSequenceAsChars();
  }

  public char getElementAtAsChar(int param1) {
    return gappedSequence.getElementAtAsChar(param1);
  }
} // DefaultGappedComplexSequence


/*
 * ChangeLog
 * $Log: DefaultGappedComplexSequence.java,v $
 * Revision 1.2  2001/04/11 17:04:43  lord
 * Added License agreements to all code
 *
 * Revision 1.1  2000/12/13 16:35:41  lord
 * Initial checkin
 *
 */
