//
//  OmTestView.m
//  OminoGobo
//
//  Created by David Van Brink on 1/5/14.
//  Copyright (c) 2014 omino. All rights reserved.
//

#import "OmTestView.h"

@implementation OmTestView


//#define ASSERT_EQUALS_INT(_expected,_actual,_message) [self log:"%s/%d\n %d (%s) == %d (%s)? %s",\
__FILE__,\
__LINE__,\
_expected,#_expected, \
_actual,#_actual, \
_message];

//#define ASSERT_EQUALS_INT(_expected,_actual,_message) [self log:"%s:%d\n",__FILE__,__LINE__];

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    // Initialization code

    omTestView = self;
    self->assertions = 0;
    self->assertionsPass = 0;
    self->assertionsFail = 0;
    self->scrollY = 0;
    
    self.showOkAssertions = YES;
    return self;
}

static const char *lastPathSegment(const char *path)
{
    int len = strlen(path);
    int lastIndexOf = -1;
    for(int i = len - 2;i >= 0; i--)
    {
        if(path[i] == '/')
        {
            lastIndexOf = i;
            break;
        }
    }
    const char *result = path + lastIndexOf + 1;
    return result;
}

- (void)assertOk:(const char *)file ok:(BOOL)ok predicateS:(const char *)predicateS line:(int)line message:(const char *)message
{
    const char *fileName = lastPathSegment(file);
    
    if(strcmp(fileName, self->lastFile))
    {
        strcpy(self->lastFile,fileName);
        [self log:"file:  %s",fileName];
    }
    
    const char *okS = ok ? "   ok   " : "--FAIL--";
    
    if(!ok || self.showOkAssertions)
        [self log:"%s %4d: <%s>?",okS,line,predicateS];
    
    if(!ok)
    {
        [self log:"          %s",message];
        NSLog(@"%s %4d: <%s>?",okS,line,predicateS);
        NSLog(@"%s",message);
    }

    self->assertions++;
    if(ok)
        self->assertionsPass++;
    else
        self->assertionsFail++;
    
    [self setNeedsDisplay];
}

-(void) assertEqualsInt:(const char*)message expected:(int)expected actual:(int)actual expectedS:(const char*)expectedS actualS:(const char *)actualS file:(const char *)file line:(int)line
{
    BOOL ok = expected == actual;
    char s[1000];
    sprintf(s,"%d (%s) == %d (%s)",expected,expectedS,actual,actualS);

    [self assertOk:file ok:ok predicateS:s line:line message:message];
    
}

-(void) assertEquals:(const char*)message expected:(NSObject *)expected actual:(NSObject *)actual expectedS:(const char*)expectedS actualS:(const char *)actualS file:(const char *)file line:(int)line
{
    BOOL ok = NO;
    if(expected == NULL && actual == NULL)
        ok = YES;
    else if(expected == NULL || actual == NULL)
        ok = NO;
    else
        ok = [expected isEqual:actual];
    char s[1000];
    sprintf(s,"<%lld> %s == <%lld> %s",(long long)expected,expectedS,(long long)actual,actualS);
    
    [self assertOk:file ok:ok predicateS:s line:line message:message];
    
}

-(void) assertEqualsFloat:(const char*)message expected:(double)expected actual:(double)actual expectedS:(const char*)expectedS actualS:(const char *)actualS file:(const char *)file line:(int)line
{
    double diff = fabs(actual - expected);
    double delta = 0.0000001;
    BOOL ok = diff < delta;
    char s[1000];
    sprintf(s,"%g (%s) == %g (%s)",expected,expectedS,actual,actualS);
    
    [self assertOk:file ok:ok predicateS:s line:line message:message];
}

-(void) assertNotNull:(const char*)message value:(id)value valueS:(const char*) valueS file:(const char *)file line:(int)line
{
    BOOL ok = value != 0;
    char s[1000];
    sprintf(s,"x%llx (%s) null",(long long)value,valueS);
    [self assertOk:file ok:ok predicateS:s line:line message:message];
}


- (void)omDrawRect:(CGRect)rect
{
    CGRect r = gBounds;
    
    if(assertionsFail > 0)
        [self gSetFillColor:0xff0000];
    else
        [self gSetFillColor:0x00ff00];
    
    [self gFillRect:r];
    
    [self gSetFont:2 size:8];
    [self gDoText];

    [self gMoveToX:20 y:30 + self->scrollY];
    [self gSetFillColor:0x0000c0];
    [self gPrintF:"%d/%d assertions\n",self->assertionsPass, self->assertions];
    [self gSetFillColor:0];
    [self gPrintF:"%s",self->log];
}

-(void)log:(char *)fmt,...
{
    char *w = self->log + strlen(self->log);
    va_list v;
    
    va_start(v,fmt);
    vsprintf(w,fmt,v);
    
    if(fmt[strlen(fmt)-1] != '\n')
        [self log:"\n"];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    int bump = [[touches allObjects][0] locationInView:self].y > 300 ? 100 : -100;
    self->scrollY -= bump;
    [self setNeedsDisplay];
}

@end
