//
//  DecorationCount.m
//  ArmorP3V1
//
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#import "DecorationCount.h"
#import "PSItem.h"
#import "PSWrap.h"
#import "Repository.h"
#import "PSMutex.h"

@implementation DecorationCount

@synthesize listDeco = _listDeco;
@synthesize listCount = _listCount;
@synthesize capacity = _capacity;

+(int)compareDecorationCount:(id)a to:(id)b {
    DecorationCount* c1 = a;
    DecorationCount* c2 = b;

    if (c2.listDeco == c1.listDeco) {
        for (int i = 0; i < c1.listDeco.count; ++ i) {
            int x = c1.listCount[i] - c2.listCount[i];
            if (x != 0) {
                if (x < 0) return -1;
                if (x > 0) return 1;
            }
        }
        return 0;
    }

    DecorationCount* compareItem = [[DecorationCount alloc]init];
    @try {
        [compareItem addAll: c1];
        [compareItem minusAll: c2];
        for(int i = 0; i < compareItem.count; ++ i) {
            if (compareItem.listCount[i] < 0) return -1;
            if (compareItem.listCount[i] > 0) return  1;
        }
    }
    @catch (NSException *exception) {
        NSLog(@"exception %@ %@", exception, [exception callStackSymbols]);
    }
    @finally {
        [compareItem release];
    }
    return 0;
}

-(NSUInteger)hash {
    NSUInteger hash = 0;
    for (int i = 0; i < _listDeco.count; ++ i) {
        PSWrap* deco = [_listDeco objectAtIndex:i];
        hash += deco.item.name.hash * _listCount[i];
    }
    return hash;
}

-(void)print:(NSMutableString*)str {
    for (int i = 0; i < _listDeco.count; ++ i) {
        PSWrap* item = [_listDeco objectAtIndex: i];
        int count = _listCount[i];
        [str appendFormat: @"%@=%d,", item.item.name, count]; 
    }
    [str appendFormat:@"hash=%d", self.hash];
}

-(BOOL)isEqual:(id)object {
    NSObject* obj = object;
    if (self == obj) {
        return TRUE;
    }
    if ([DecorationCount compareDecorationCount:self to:obj] == 0) {
        return TRUE;
    }
    return FALSE;
}

-(id)init {
    self = [super init];
    if (self) {
        _capacity = 10;
        _listDeco = [[NSMutableArray alloc]initWithCapacity:_capacity];
        _listCount = calloc(sizeof(int), _capacity);

        if (_listDeco == nil || _listCount == nil) {
            [[PSMutex mainMutex] raiseMemoryError];
        }
    }else {
        [[PSMutex mainMutex] raiseMemoryError];
    }
    [[PSMutex mainMutex] showMemoryAlertIfError];
    [[PSMutex mainMutex] showMemoryAlertIfError];
    return self;
}

-(id)initWith:(id)with {
    DecorationCount* from = with;
    self = [super init];
    if (self) {
        self.capacity = from.capacity;
        self.listDeco = from.listDeco;
        free(self.listCount);
        self.listCount = calloc(sizeof(int), self.capacity);
        for(int i = 0; i < from.count; ++ i){
            self.listCount[i] = from.listCount[i];
        }
    }else {
        [[PSMutex mainMutex] raiseMemoryError];
    }
    [[PSMutex mainMutex] showMemoryAlertIfError];
    return self;
}


-(void)resetWithColumn:(NSMutableArray*)listDeco {
    free(_listCount);

    _capacity = listDeco.count;
    
    [_listDeco release];
    _listDeco = listDeco;
    [_listDeco retain];
    _listCount = calloc(sizeof(int), _capacity);
}

-(void)dealloc {
    [_listDeco release];
    free(_listCount);
    [super dealloc];
}

-(void)ensureCapacity:(int)newCap {
    if (newCap < 5) {
        newCap = 5;
    }
    int x = _capacity;
    while (x < newCap) {
        x += 5;
    }
    int* newInt = calloc(sizeof(int), x);
    for (int i = 0; i < _capacity; ++ i) {
        newInt[i] = _listCount[i];
    }
    free(_listCount);
    _listCount = newInt;
}

-(int)count {
    return _listDeco.count;
}

-(void)increment:(PSWrap*) e {
    for(int i = 0; i < self.count; ++ i) {
        PSWrap* p = [_listDeco objectAtIndex:i];
        if (p.item == e.item) {
            _listCount[i] ++;
            return;
        }
    }
    if (_listDeco.retainCount >= 2) {
        [_listDeco release];
        _listDeco = [[NSMutableArray alloc]initWithArray:_listDeco];
    }
    [_listDeco addObject:e];
    
    int n = _listDeco.count;
    [self ensureCapacity: n + 1];
    _listCount[n] = 1;
}

-(void)set:(PSWrap*) e : (int) x {
    for(int i = 0; i < self.count; ++ i) {
        PSWrap* p = [_listDeco objectAtIndex:i];
        if (p.item == e.item) {
            _listCount[i] = x;
            return;
        }
    }
    if (_listDeco.retainCount >= 2) {
        [_listDeco release];
        _listDeco = [[NSMutableArray alloc]initWithArray:_listDeco];
    }
    [_listDeco addObject:e];
    
    int n = _listDeco.count;
    [self ensureCapacity: n + 1];
    _listCount[n] = x;
}

-(void)putAll:(DecorationCount*)set {
    [_listDeco release];
    _listDeco = set.listDeco;
    [_listDeco retain];

    _capacity = _listDeco.count;
    int* oldCount = _listCount;
    _listCount = calloc(sizeof(int), _capacity);
    
    for (int i = 0; i < self.count; ++ i) {
        _listCount[i] = set.listCount[i];
    }
    free(oldCount);
}

-(void)addAll:(DecorationCount*)set {
    for(int i = 0; i < set.count; ++ i) {
        PSWrap* e = [set.listDeco objectAtIndex: i];
        int n = set.listCount[i];
                 
        BOOL found = FALSE;
        for (int x = 0; x < self.count; ++ x) {
            PSWrap* e2 = [_listDeco objectAtIndex: x];
            if (e2 == e) {
                _listCount[x] += n;
                found = TRUE;
                break;
            }
        }
        if (!found) {
            if (_listDeco.retainCount >= 2) {
                [_listDeco release];
                _listDeco = [[NSMutableArray alloc]initWithArray:_listDeco];
            }
            [self ensureCapacity:_listDeco.count + 2];
            [_listDeco addObject:e];
            _listCount[_listDeco.count -1] = n;
        }
    }
}

-(void)minusAll:(DecorationCount*)set {
    for(int i = 0; i < set.count; ++ i) {
        PSWrap* e = [set.listDeco objectAtIndex: i];
        int n = set.listCount[i];
        
        BOOL found = FALSE;
        for (int x = 0; x < self.count; ++ x) {
            PSWrap* e2 = [_listDeco objectAtIndex: x];
            if (e2 == e) {
                _listCount[x] -= n;
                found = TRUE;
                break;
            }
        }
        if (!found) {
            if (_listDeco.retainCount >= 2) {
                [_listDeco release];
                _listDeco = [[NSMutableArray alloc]initWithArray:_listDeco];
            }
            [self ensureCapacity:_listDeco.count + 2];
            [_listDeco addObject:e];
            _listCount[_listDeco.count - 1] = -n;
        }
    }
}
    
-(void)clear {
    for (int i = 0; i < self.count; ++ i) {
        _listCount[i] = 0;
    }
}

-(BOOL)isEmpty {
    for (int i = 0 ; i < self.count; ++ i) {
        if (_listCount[i] != 0) {
            return FALSE;
        }
    }
    return TRUE;
}

-(NSInteger)get:(PSItem*)e {
    for (int i = 0 ; i < self.count; ++ i) {
        if ([_listDeco objectAtIndex:i] == e) {
            return _listCount[i];
        }
    }
    return 0;
}

-(PSWrap*)decoAt:(int)pos {
    return [_listDeco objectAtIndex:pos];
}

@end
