//
//  BaseVariable.m
//  SFS2X
//
//  Created by Lapo on 26/10/16.
//  Copyright © 2016 A51 Integrated | http://a51integrated.com. All rights reserved.
//

#import "BaseVariable.h"
#import "VariableType.h"
#import "SFSException.h"
#import "SFSObject.h"
#import "SFSArray.h"

@implementation BaseVariable

@synthesize name = _name;
@synthesize type = _type;

#pragma mark Constructors

-(id)initWithName:(NSString *)name value:(id)value type:(NSInteger)type
{
    if ((self = [super init]))
    {

        _name = name;
        
        if (type > -1)
        {
            _value = value;
            _type = [VariableType getTypeName:type];
        }
        else
            [self setValue:value];
        
    }
    
    return self;
}

+(id)variableWithName:(NSString *)name value:(id)value type:(NSInteger)type {
    BaseVariable* var = [[BaseVariable alloc] initWithName:name value:value type:type];
    return var;
}

+(id)variableWithName:(NSString *)name value:(id)value {
    BaseVariable* var = [[BaseVariable alloc] initWithName:name value:value type:-1];
    return var;
}

#pragma mark UserVariable protocol

-(NSString *)name
{
    return _name;
}

-(NSString *)type
{
    return _type;
}

-(id)getValue
{
    return _value;
}

-(BOOL)getBoolValue
{
    return [(NSNumber *)_value boolValue];
}

-(NSInteger)getIntValue
{
    return [(NSNumber *)_value intValue];
}

-(NSNumber *)getDoubleValue
{
    return (NSNumber *)_value;
}

-(NSString *)getStringValue
{
    return _value;
}

-(id <ISFSObject>)getSFSObjectValue
{
    return _value;
}

-(id <ISFSArray>)getSFSArrayValue
{
    return _value;
}

-(BOOL)isNull
{
    return [_type isEqualToString:[VariableType getTypeName:VariableType_NULL]];
}

-(id<ISFSArray>)toSFSArray
{
    
    id <ISFSArray> sfsa = [SFSArray newInstance];
    
    [sfsa addUtfString:_name];
    
    [sfsa addByte:[VariableType getTypeFromName:_type]];
    
    [self populateArrayWithValue:sfsa];
    
    return sfsa;
    
}

#pragma mark -

-(void)setValue:(id)value
{
    _value = value;
    
    if (_value == nil)
        _type = [VariableType getTypeName:VariableType_NULL];
    
    else
    {
        
        if ([value isKindOfClass:[NSNumber class]])
        {
            
            if (strcmp([(NSNumber *)value objCType], @encode(BOOL)) == 0)
                _type = [VariableType getTypeName:VariableType_BOOL];
            
            else if(strcmp([(NSNumber *)value objCType], @encode(int)) == 0)
                _type = [VariableType getTypeName:VariableType_INT];
            
            else
                _type = [VariableType getTypeName:VariableType_DOUBLE];
        }
        
        else if ([value isKindOfClass:[NSString class]])
            _type = [VariableType getTypeName:VariableType_STRING];
        
        else if ([value isKindOfClass:[SFSObject class]])
            _type = [VariableType getTypeName:VariableType_OBJECT];
        
        else if ([value isKindOfClass:[SFSArray class]])
            _type = [VariableType getTypeName:VariableType_ARRAY];
        
        else
            @throw [SFSException exceptionWithReason:[NSString stringWithFormat:@"Unsupported SFS Variable type: %@", NSStringFromClass([value class])]];

    }
}

-(void)populateArrayWithValue:(id <ISFSArray>)arr
{
    int typeId = (int)[VariableType getTypeFromName:_type];
    
    if (typeId == VariableType_NULL)
        [arr addNull];
    
    else if (typeId == VariableType_BOOL)
        [arr addBool:[self getBoolValue]];
    
    else if (typeId == VariableType_INT)
        [arr addInt:[self getIntValue]];
    
    else if (typeId == VariableType_DOUBLE)
        [arr addDouble:[self getDoubleValue]];
    
    else if (typeId == VariableType_STRING)
        [arr addUtfString:[self getStringValue]];
    
    else if (typeId == VariableType_OBJECT)
        [arr addSFSObject:[self getSFSObjectValue]];
    
    else if (typeId == VariableType_ARRAY)
        [arr addSFSArray:[self getSFSArrayValue]];
}

-(NSString *)description {
    return [NSString stringWithFormat:@"[UVar: %@, type: %@, value: %@]", _name, _type, _value];
}

@end
