/** filename: {{&sdknameLower}}/{{&sdkname}}.m **/
#import "{{&sdkname}}.h"

@implementation {{&sdkname}}

static NSString *_domain;
static NSNumber *_port;
static NSNumber *_timeout;
static NSDictionary *_headers;
static CachePolicy _cachePolicyType;
static NSNumber *_cachePolicyDuration;
static NSCache *_cache;

+ (NSString *)domain {
    @synchronized(self) {
        if (_domain == nil) {
            return @"{{&domain}}";
        }
        return _domain;
    }
}
+ (void)setDomain:(NSString *)value {
    @synchronized(self) { _domain = value; }
}

+ (NSNumber *)port {
    @synchronized(self) {
        return _port;
    }
}
+ (void)setPort:(NSNumber *)value {
    @synchronized(self) { _port = value; }
}

+ (NSNumber *)timeout {
    @synchronized(self) {
        if (_timeout == nil) {
            return [NSNumber numberWithDouble:30000];
        }
        return _timeout;
    }
}
+ (void)setTimeout:(NSNumber *)value {
    @synchronized(self) { _timeout = value; }
}

+ (void)setHeader:(NSString *)key withValue:(NSString *)val {
    @synchronized(self) {
        if (_headers == nil) {
            _headers = [[NSMutableDictionary alloc] init];
        }
        [_headers setValue:val forKey:key];
    }
}

+ (NSString *)getHeader:(NSString *)key {
    @synchronized(self) {
        if (_headers != nil) {
            return [_headers valueForKey:key];
        }
        return nil;
    }
}

+ (NSString *)apiKey {
    return [self getHeader:@"APIKey"];
}
+ (void)setAPIKey:(NSString *)value {
    [self setHeader:@"APIKey" withValue:value];
}

+ (NSString *)authorization {
    return [self getHeader:@"Authorization"];
}
+ (void)setAuthorization:(NSString *)value {
    if ([value containsString:@"Basic "]) {
        [self setHeader:@"Authorization" withValue:value];
    }
    else if ([value hasSuffix:@":"]) {
        [self setHeader:@"Authorization" withValue:[NSString stringWithFormat:@"Basic %@", [[value dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0]]];
    }
    else {
        [self setHeader:@"Authorization" withValue:[NSString stringWithFormat:@"Basic %@", [[[NSString stringWithFormat:@"%@:", value] dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0]]];
    }
}

+ (NSDictionary *) getDefaultHeaders {
    @synchronized(self) { return _headers; }
}

+ (NSString *) getURL:(NSString *)path {
    NSString *url = self.domain;
    if (self.port != nil) {
        url = [NSString stringWithFormat:@"%@:%@", url, self.port];
    }
    return [NSString stringWithFormat:@"%@%@", url, path];
}

+ (CachePolicy)cachePolicyType {
    @synchronized(self) { return _cachePolicyType; }
}
+ (void)setCachePolicyType:(CachePolicy)value {
    @synchronized(self) { _cachePolicyType = value; }
}

+ (NSNumber *)cachePolicyDuration {
    @synchronized(self) {
        if (_cachePolicyDuration == nil) {
            return [NSNumber numberWithLong:60 * 60 * 1000];
        }
        return _cachePolicyDuration;
    }
}

+ (void)setCachePolicyDuration:(NSNumber *)value {
    @synchronized(self) { _cachePolicyDuration = value; }
}

+ (NSDictionary *) readCache:(NSString *)hash {
    if (_cache == nil) {
        return nil;
    }
    NSDictionary *wrapped = [_cache objectForKey:hash];
    if (wrapped != nil) {
        long long now = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0);
        if (now < [[wrapped valueForKey:@"until"] longValue]) {
            return [wrapped valueForKey:@"result"];
        }
    }
    return nil;
}

+ (void) writeCache:(NSString *)hash with:(NSDictionary *)result and:(NSNumber *)duration {
    if (_cache == nil) {
        _cache = [[NSCache alloc] init];
    }
    long long now = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0);
    [_cache setObject:[NSDictionary dictionaryWithObjectsAndKeys:
                       result, @"result",
                       [NSNumber numberWithDouble:([duration longValue] + now)], @"until",
                       nil] forKey:hash cost:[duration intValue]];
}

@end

