//
//  BCNucleotide.m
//  BioCocoa
//
//  Created by John Timmer on 2/25/05.
//  Copyright (c) 2003-2009 The BioCocoa Project.
//  All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions
//  are met:
//  1. Redistributions of source code must retain the above copyright
//  notice, this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright
//  notice, this list of conditions and the following disclaimer in the
//  documentation and/or other materials provided with the distribution.
//  3. The name of the author may not be used to endorse or promote products
//  derived from this software without specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
//  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
//  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
//  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
//  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
//  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#import "BCNucleotide.h"
#import	"BCStringDefinitions.h"

#import "BCInternal.h"

@implementation BCNucleotide

- (id)initWithSymbolChar:(unsigned char)aChar
{
    if ( (self = [super initWithSymbolChar: aChar]) )
    {
        complement = nil;
        complements = nil;
    }
    
    return self;
}


- (void)dealloc
{   
    [complement release];
    [complements release];
	
	[super dealloc];
}



- (void) initializeComplementRelationships {
    // THIS METHOD IS CALLED AFTER OBJECT INITIALIZATION BECAUSE IT 
    // REQUIRES THE EXISTENCE OF ALL THE OTHER SYMBOLS IN ORDER TO WORK
    // IT SHOULD BE CALLED THE FIRST TIME ONE OF THESE INSTANCE OBJECTS IS NEEDED
    
    NSString		*symbolReference;
    NSArray			*infoArray;
    NSEnumerator	*objectEnumerator;
    NSMutableArray	*tempArray;
    BCSymbol		*tempSymbol;
    
    symbolReference = [[self symbolInfo] objectForKey: BCSymbolComplementProperty];
    
    if ( symbolReference != nil || [symbolReference length] > 0 )
    {
        complement = [(BCNucleotide *)[self class] performSelector: NSSelectorFromString( symbolReference )];
    }
    
    infoArray = [[self symbolInfo] objectForKey: BCSymbolAllComplementsProperty];
    
    if ( infoArray != nil || [infoArray count] > 0 )
    {
        objectEnumerator = [infoArray objectEnumerator];
        tempArray = [NSMutableArray array];
        
        while ( (symbolReference = [objectEnumerator nextObject]) )
        {
            if ( symbolReference != nil || [symbolReference length] > 0 )
            {
                tempSymbol = [(BCNucleotide *)[self class] performSelector: NSSelectorFromString( symbolReference )];
                
                if ( tempSymbol != nil )
                    [tempArray addObject: tempSymbol];
            }
        }
        
        complements = [[NSSet setWithArray: tempArray] retain];
    }
    
}



///////////////////////////////////////////////////////////
//  COMPLEMENTATION METHODS
///////////////////////////////////////////////////////////


- (BCNucleotide  *)complement  {
    if ( complement == nil )
        [self initializeComplementRelationships];
    
    return (BCNucleotide  *)complement;
}


- (NSSet *)complements  {
    if ( complements == nil )
        [self initializeComplementRelationships];
    
    return complements;
}


- (BOOL) complementsSymbol: (BCNucleotide *)entry {
    if ( complements == nil )
        [self initializeComplementRelationships];
        
// the following is the equivalent of return [complements containsObject: entry];
    return SET_CONTAINS_VALUE(complements, entry);
}


- (BOOL) isComplementOfSymbol: (BCNucleotide *)entry {
    return [entry complementsSymbol: self];
}



@end
