//
//  Post.m
//  Blog
//
//  Created by Sami Samhuri on 2014-11-23.
//  Copyright (c) 2014 Guru Logic Inc. All rights reserved.
//

#import "Post.h"
#import "NSDate+marshmallows.h"
#import "NSString+marshmallows.h"
#import <Mantle/MTLValueTransformer.h>

@implementation Post

@synthesize objectID = _objectID;
@synthesize slug = _slug;
@synthesize author = _author;
@synthesize title = _title;
@synthesize date = _date;
@synthesize time = _time;
@synthesize body = _body;
@synthesize path = _path;
@synthesize url = _url;
@synthesize formattedDate = _formattedDate;

+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    return @{
            @"objectID" : @"id",
            @"slug"     : @"slug",
            @"author"   : @"author",
            @"title"    : @"title",
            @"date"     : @"date",
            @"draft"    : @"draft",
            @"body"     : @"body",
            @"path"     : @"url",
            @"url"      : @"link",
            @"time"     : @"", // ignore
    };
}

+ (NSValueTransformer *)urlJSONTransformer {
    return [MTLValueTransformer transformerUsingForwardBlock:^NSURL *(NSString *str, BOOL *success, NSError **error) {
        return [NSURL URLWithString:str];
    } reverseBlock:^NSString *(NSURL *url, BOOL *success, NSError **error) {
        return [url absoluteString];
    }];
}

+ (instancetype)newDraftWithTitle:(NSString *)title body:(NSString *)body url:(NSURL *)url {
    NSDictionary *fields = @{
            @"new"   : @(YES),
            @"draft" : @(YES),
            @"title" : title ?: @"",
            @"body"  : body ?: @"",
            @"url"   : url ?: [NSNull null],
    };
    return [[self alloc] initWithDictionary:fields error:nil];
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

- (instancetype)copyWithBody:(NSString *)body {
    return [self copyWithTitle:self.title body:body url:self.url new:self.new];
}

- (instancetype)copyWithTitle:(NSString *)title {
    return [self copyWithTitle:title body:self.body url:self.url new:self.new];
}

- (instancetype)copyWithURL:(NSURL *)url {
    return [self copyWithTitle:self.title body:self.body url:url new:self.new];
}

- (instancetype)copyWithNew:(BOOL)isNew {
    return [self copyWithTitle:self.title body:self.body url:self.url new:isNew];
}

- (instancetype)copyWithTitle:(NSString *)title body:(NSString *)body url:(NSURL *)url new:(BOOL)isNew {
    return [[Post alloc] initWithDictionary:@{
            @"objectID" : self.objectID ?: [NSNull null],
            @"slug"     : self.slug ?: [NSNull null],
            @"author"   : self.author ?: [NSNull null],
            @"title"    : title ?: [NSNull null],
            @"date"     : self.date ?: [NSNull null],
            @"body"     : body ?: [NSNull null],
            @"path"     : self.path ?: [NSNull null],
            @"url"      : url ?: [NSNull null],
            @"draft"    : @(self.draft),
            @"new"      : @(isNew),
    } error:nil];
}

- (BOOL)isEqualToPost:(Post *)other {
    return [self.objectID isEqualToString:other.objectID]
            && [self.path isEqualToString:other.path]
            && ((!self.title && !other.title) || [self.title isEqual:other.title])
            && ((!self.body && !other.body) || [self.body isEqual:other.body])
            && self.draft == other.draft
            && ((!self.url && !other.url) || [self.url isEqual:other.url]);
    // include "new" here too?
}

- (BOOL)isEqual:(id)object {
    return self == object || ([object isMemberOfClass:[Post class]] && [self isEqualToPost:object]);
}

- (NSUInteger)hash {
    return [(self.objectID ?: self.slug) hash];
}

- (NSString *)objectID {
    if (!_objectID && _draft) {
        CFUUIDRef uuid = CFUUIDCreate(NULL);
        CFStringRef uuidString = CFUUIDCreateString(NULL, uuid);
        CFRelease(uuid);
        _objectID = (__bridge NSString *)uuidString;
    }
    return _objectID;
}

- (NSString *)author {
    if (!_author) {
        _author = @"Sami Samhuri";
    }
    return _author;
}

- (NSString *)slug {
    if (!_slug && !self.draft && self.title) {
        _slug = [[[[[self.title lowercaseString]
                mm_stringByReplacing:@"'" with:@""]
                mm_stringByReplacing:@"[^[:alpha:]\\d_]" with:@"-"]
                mm_stringByReplacing:@"^-+|-+$" with:@""]
                mm_stringByReplacing:@"-+" with:@"-"];
    }
    return _slug;
}

- (BOOL)isLink {
    return self.url != nil;
}

- (NSDate *)time {
    if (!_time && self.timestamp) {
        _time = [NSDate dateWithTimeIntervalSince1970:self.timestamp];
    }
    return _time;
}

- (NSString *)formattedDate {
    if (!_formattedDate && self.time) {
        _formattedDate = [NSString stringWithFormat:@"%ld-%02ld-%02ld", (long)self.time.mm_year, (long)self.time.mm_month, (long)self.time.mm_day];
    }
    return _formattedDate;
}

- (NSString *)path {
    if (!_path) {
        if (self.draft) {
            _path = [NSString stringWithFormat:@"/posts/drafts/%@", self.objectID];
        }
        else {
            NSAssert(self.slug && self.date, @"slug and date are required");
            NSString *paddedMonth = [self paddedMonthForDate:self.time];
            _path = [NSString stringWithFormat:@"/posts/%ld/%@/%@", (long)self.time.mm_year, paddedMonth, self.slug];
        }
    }
    return _path;
}

- (NSString *)paddedMonthForDate:(NSDate *)date {
    return [NSString stringWithFormat:@"%02ld", (long)date.mm_month];
}

@end
