//
// CreditCard.m
// GotoBus
//
// Created by haibara on 2/11/15.
//
//

#import "CreditCard.h"
#import "Lang.h"
#import "SDK.h"
#import "BeanUtils.h"
#import "CocoaUtils.h"
#import "RandomUtils.h"
#import <BlocksKit/BlocksKit.h>
#import <LoremIpsum/LoremIpsum.h>
#import "Utility.h"
#import "Vars.h"

@implementation CreditCard

- (instancetype)init {
	if (self = [super init]) {
		self.card_type = 1;
		self.address = [[Address alloc] init];
		self.address.country = [Address preferredCountryCode];
	}
	return self;
}

- (BOOL)isEqual:(id)object {
	if (self == object) {
		return YES;
	}
	if (![object isKindOfClass:self.class]) {
		return NO;
	}
	return self.hash == [object hash];
}

- (NSUInteger)hash {
    return self.ccid != 0 ? self.ccid : [super hash];
}

- (id)copyWithZone:(NSZone *)zone {
	return [BeanUtils copyWithZone:zone origin:self];
}

#pragma mark - Property

- (BOOL)persistent {
	return !self.transient;
}

- (void)setPersistent:(BOOL)persistent {
	self.transient = !persistent;
}

- (CardIOCreditCardType)creditCardType {
	switch (self.card_type) {
		case 1:
			return CardIOCreditCardTypeMastercard;

		case 2:
			return CardIOCreditCardTypeVisa;

		case 3:
			return CardIOCreditCardTypeAmex;

		default:
			return CardIOCreditCardTypeUnrecognized;
	}
}

- (void)setCreditCardType:(CardIOCreditCardType)creditCardType {
	switch (creditCardType) {
		case CardIOCreditCardTypeMastercard:
			self.card_type = 1;
			break;

		case CardIOCreditCardTypeVisa:
			self.card_type = 2;
			break;

		case CardIOCreditCardTypeAmex:
			self.card_type = 3;
			break;

		default:
			break;
	}
}

- (NSString *)cardTypeName {
	return [CardIOCreditCardInfo displayStringForCardType:self.creditCardType usingLanguageOrLocale:[CocoaUtils applicationLocale].localeIdentifier];
}

- (UIImage *)cardTypeImage {
	return [CardIOCreditCardInfo logoForCardType:self.creditCardType];
}

#pragma mark - Public

- (void)setValuesForKeysWithCreditCardInfo:(CardIOCreditCardInfo *)cardInfo {
	self.name_on_card = cardInfo.cardholderName;
	self.creditCardType = cardInfo.cardType;
	self.card_number = cardInfo.cardNumber;
	self.expire_month = [NSString stringWithFormat:@"%02d", cardInfo.expiryMonth];
	self.expire_year = [NSString stringWithFormat:@"%d", cardInfo.expiryYear];
}

- (NSAttributedString *)attributedRedactedCardNumberIfDefaultAppendingWithFormat:(NSString *)format {
	NSString *redactedCardNumber = self.card_number.length >= 4 ? [NSString stringWithFormat:format, [self.card_number substringFromIndex:self.card_number.length - 4]] : nil;
	if (self.isDefault) {
		return [Utility attributedDefaultAppendingWithString:redactedCardNumber];
	} else {
		return [[NSAttributedString alloc] im_initWithString:redactedCardNumber];
	}
}

- (NSString *)innerXML {
	NSMutableString *string = [NSMutableString string];
	[string im_appendString:[CocoaUtils xmlStringWithNonZeroProperties:[BeanUtils describe:self keys:[ArrayUtils remove:[BeanUtils keysForAccessibleSimplePropertyWithClass:self.class] element:@"transient"]]]];
	if (self.address) {
		[string im_appendString:[self.address innerXML]];
	}
	return [NSString stringWithString:string];
}

+ (CreditCard *)primaryOfCreditCards:(NSArray *)creditCards {
	CreditCard *creditCard = [self defaultOfCreditCards:creditCards];
	return creditCard ? creditCard : creditCards.firstObject;
}

+ (CreditCard *)defaultOfCreditCards:(NSArray *)creditCards {
	return [creditCards bk_match:^BOOL (CreditCard *obj) {
		return obj.isDefault;
	}];
}

+ (CreditCard *)randomCreditCard {
	CreditCard *creditCard = [[CreditCard alloc] init];
	creditCard.name_on_card = [LoremIpsum wordsWithNumber:2].capitalizedString;
	creditCard.card_type = arc4random_uniform(3) + 1;
	creditCard.card_number = [NSString stringWithFormat:@"%@", [RandomStringUtils randomNumeric:creditCard.card_type != 3 ? 16 : 15]];
	creditCard.expire_month = [NSString stringWithFormat:@"%02d", [DateUtils getFragment:[NSDate date] unit:NSCalendarUnitMonth]];
	creditCard.expire_year = [NSString stringWithFormat:@"%d", [DateUtils getFragment:[NSDate date] unit:NSCalendarUnitYear]];
	creditCard.address.street = [LoremIpsum sentence].capitalizedString;
	creditCard.address.city = [LoremIpsum word].capitalizedString;
	creditCard.address.state = [RandomUtils nextObject:[Address knownStates]];
	creditCard.address.zipcode = [NSString stringWithFormat:@"%d", abs((int32_t)[LoremIpsum word].hash)];
	creditCard.isDefault = [RandomUtils nextBoolean];
	return creditCard;
}

@end
