//
//  Object.m
//  OpenStack
//
//  Created by Mike Mayo on 12/7/10.
//  The OpenStack project is provided under the Apache 2.0 license.
//

#import "StorageObject.h"
#import "ComputeModel.h"
#import "NSObject+NSCoding.h"

@implementation StorageObject

@synthesize name, fullPath, hash, bytes, contentType, lastModified, data, publicURI, sharing, metadata, iso8601DateString, lastModifiedString;

#pragma mark - Object lifecycle

+ (StorageObject *)fromJSON:(NSDictionary *)dict {
    StorageObject *object = [[[StorageObject alloc] init] autorelease];
    
    object.name = [dict objectForKey:@"name"]; // this may be shortened by folder parsing later
    object.fullPath = [dict objectForKey:@"name"];
    object.hash = [dict objectForKey:@"x_object_hash"];
    object.bytes = [[dict objectForKey:@"bytes"] intValue];
    object.contentType = [dict objectForKey:@"content_type"];
    //object.lastModified = [ComputeModel dateFromString:[dict objectForKey:@"last_modified"]];
    object.iso8601DateString = [dict objectForKey:@"last_modified"];
    object.publicURI = [dict objectForKey:@"x_object_public"];
    object.sharing = [dict objectForKey:@"x_object_sharing"];
    object.metadata = nil;
    return object;
}

- (NSComparisonResult)compareByName:(id)item {
    return [self.name caseInsensitiveCompare:[item name]];
}

- (NSComparisonResult)compareByDate:(id)item {
    return [self.lastModifiedString caseInsensitiveCompare:[item lastModifiedString]];
}

#pragma mark - Serialization

- (id)initWithCoder:(NSCoder *)coder {
    if ((self = [super init])) {
        [self autoDecode:coder];
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)coder {
    [self autoEncodeWithCoder:coder];
}

#pragma mark - Memory Management

-(void)dealloc {
	[name release];
    [fullPath release];
	[hash release];
	[contentType release];
	[lastModified release];
	[data release];
	[metadata release];
    [iso8601DateString release];
    [lastModifiedString release];
	[super dealloc];
}

#pragma mark - Properties

- (NSString *)lastModifiedString {
    if (!lastModifiedString) {
        if (!self.lastModified && [self.iso8601DateString length])
            self.lastModified = [ComputeModel dateFromString:self.iso8601DateString];
        if (self.lastModified)
            lastModifiedString = [[ComputeModel localDateDescriptionFromDate:self.lastModified] retain];
    }
    return lastModifiedString;
}

#pragma mark - Actions

- (void)setPropertiesfromResponseHeaders:(NSDictionary *)headers {
    self.hash = [headers objectForKey:@"X-Object-Hash"];
    self.bytes = [[headers objectForKey:@"Content-Length"] intValue];
    self.contentType = [headers objectForKey:@"Content-Type"];
    self.lastModified = [ComputeModel dateFromRFC1123String:[headers objectForKey:@"Last-Modified"]];
    self.publicURI = [headers objectForKey:@"X-Object-Public"];
    self.sharing = [headers objectForKey:@"X-Object-Sharing"];
    
    self.metadata = [NSMutableDictionary dictionary];
    for (NSString *key in headers) {
        if ([key hasPrefix:@"X-Object-Meta-"]) {
            NSString *metadataValue = [headers objectForKey:key];
            NSString *metadataKey = [key substringFromIndex:14];
            [self.metadata setObject:metadataValue forKey:metadataKey];
        }
    }
}

-(NSString *)humanizedBytes {
	NSString *result;	
	if (self.bytes >= 1024000000) {
		result = [NSString stringWithFormat:@"%.2f GiB", self.bytes / 1024000000.0];
	} else if (self.bytes >= 1024000) {
		result = [NSString stringWithFormat:@"%.2f MiB", self.bytes / 1024000.0];
	} else if (self.bytes >= 1024) {
		result = [NSString stringWithFormat:@"%.2f KiB", self.bytes / 1024.0];
	} else {
		result = [NSString stringWithFormat:@"%i bytes", self.bytes];
	}
	return result;
}

- (BOOL)isPlayableMedia {
    // check file extension
    NSString *extensionPattern = @"^.+\\.((mov)|(m4a)|(mp3)|(wav)|(aiff)|(aac)|(aif)|(aifc)|(amr)|(caf)|(m2a)|(m4p)|(mp4)|(mpv)|(3gp))$";
    NSRegularExpression *extensionRegex = [NSRegularExpression regularExpressionWithPattern:extensionPattern options:NSRegularExpressionCaseInsensitive error:nil];
    NSInteger matches = [extensionRegex numberOfMatchesInString:self.name options:0 range:NSMakeRange(0, [self.name length])];

    // check content type
    NSString *contentTypePattern = @"^(video|audio)/";
    NSRegularExpression *contentTypeRegex = [NSRegularExpression regularExpressionWithPattern:contentTypePattern options:NSRegularExpressionCaseInsensitive error:nil];
    matches += [contentTypeRegex numberOfMatchesInString:self.contentType options:0 range:NSMakeRange(0, [self.contentType length])];
    
    return matches > 0;
}

- (NSMutableDictionary *)permissions {
    NSMutableDictionary *permissions = [NSMutableDictionary dictionary];
    if (self.sharing.length) {
        for (NSString *sharingList in [self.sharing componentsSeparatedByString:@";"]) {
            NSArray *components = [sharingList componentsSeparatedByString:@"="];
            NSString *type = [components objectAtIndex:0];
            if ([type hasPrefix:@" "]) {
                type = [type substringFromIndex:1];
            }
            for (NSString *user in [[components objectAtIndex:1] componentsSeparatedByString:@","]) {
                [permissions setObject:type forKey:user];
            }
        }
    }
    return permissions;
}

- (void)setPermissions:(NSMutableDictionary *)permissions {
    NSMutableString *readSharingList = nil;
    NSMutableString *writeSharingList = nil;
    for (NSString *user in permissions) {
        if ([[permissions objectForKey:user] isEqual:@"read"]) {
            if (!readSharingList) {
                readSharingList = [NSMutableString stringWithFormat:@"read=%@", user];
            } else {
                [readSharingList appendFormat:@",%@", user];
            }
        } else if ([[permissions objectForKey:user] isEqual:@"write"]) {
            if (!writeSharingList) {
                writeSharingList = [NSMutableString stringWithFormat:@"write=%@", user];
            } else {
                [writeSharingList appendFormat:@",%@", user];
            }
        }
    }
    if (readSharingList && writeSharingList) {
        self.sharing = [NSString stringWithFormat:@"%@;%@", readSharingList, writeSharingList];
    } else if (readSharingList) {
        self.sharing = readSharingList;
    } else if (writeSharingList) {
        self.sharing = writeSharingList;
    }
}

@end
