// // CLTimezoneData.m // Clocker // // Created by Abhishek Banthia on 12/22/15. // // #import "CLAPIConnector.h" #import "CLTimezoneData.h" #import "CommonStrings.h" #import "DateTools.h" #import "PanelController.h" #include #include #include "EDSunriseSet.h" @implementation CLTimezoneData -(instancetype)initWithDictionary:(NSDictionary *)dictionary { self = [super init]; if (self) { self.customLabel = dictionary[CLCustomLabel]; self.timezoneID = dictionary[CLTimezoneID]; self.latitude = dictionary[@"latitude"]; self.longitude = dictionary[@"longitude"]; self.place_id = dictionary[CLPlaceIdentifier]; self.formattedAddress = dictionary[CLTimezoneName]; self.isFavourite = @(NSOffState); self.selectionType = CLCitySelection; } return self; } + (instancetype)getCustomObject:(NSData *)encodedData { if (encodedData) { if ([encodedData isKindOfClass:[NSDictionary class]]) { CLTimezoneData *newObject = [[self alloc] initWithDictionary:(NSDictionary *)encodedData]; return newObject; } CLTimezoneData *object = [NSKeyedUnarchiver unarchiveObjectWithData:encodedData]; return object; } return nil; } - (void)encodeWithCoder:(NSCoder *)coder { [coder encodeObject:self.place_id forKey:@"place_id"]; [coder encodeObject:self.formattedAddress forKey:@"formattedAddress"]; [coder encodeObject:self.customLabel forKey:@"customLabel"]; [coder encodeObject:self.timezoneID forKey:@"timezoneID"]; [coder encodeObject:self.nextUpdate forKey:@"nextUpdate"]; [coder encodeObject:self.latitude forKey:@"latitude"]; [coder encodeObject:self.longitude forKey:@"longitude"]; [coder encodeObject:self.isFavourite forKey:@"isFavourite"]; [coder encodeObject:self.sunriseTime forKey:@"sunriseTime"]; [coder encodeObject:self.sunsetTime forKey:@"sunsetTime"]; [coder encodeInteger:self.selectionType forKey:@"selectionType"]; } - (instancetype)initWithCoder:(NSCoder *)coder { self = [super init]; if (self) { self.place_id = [coder decodeObjectForKey:@"place_id"]; self.formattedAddress = [coder decodeObjectForKey:@"formattedAddress"]; self.customLabel = [coder decodeObjectForKey:@"customLabel"]; self.timezoneID = [coder decodeObjectForKey:@"timezoneID"]; self.nextUpdate = [coder decodeObjectForKey:@"nextUpdate"]; self.latitude = [coder decodeObjectForKey:@"latitude"]; self.longitude = [coder decodeObjectForKey:@"longitude"]; self.isFavourite = [coder decodeObjectForKey:@"isFavourite"]; self.sunriseTime = [coder decodeObjectForKey:@"sunriseTime"]; self.sunsetTime = [coder decodeObjectForKey:@"sunsetTime"]; self.selectionType = [coder decodeIntegerForKey:@"selectionType"]; } return self; } -(NSString *)description { return [NSString stringWithFormat:@"TimezoneID: %@\nFormatted Address: %@\nCustom Label: %@\nLatitude: %@\nLongitude:%@\nPlaceID: %@\nisFavourite: %@\nSunrise Time: %@\nSunset Time: %@\nSelection Type: %zd", self.timezoneID, self.formattedAddress, self.customLabel, self.latitude, self.longitude, self.place_id, self.isFavourite, self.sunriseTime, self.sunsetTime, self.selectionType]; } - (NSString *)formatStringShouldContainCity:(BOOL)value { if (self.customLabel.length > 0) { return self.customLabel; } if ([self.formattedAddress length] > 0) { return self.formattedAddress; } else if (self.timezoneID) { NSString *timezoneID = self.timezoneID; NSRange range = [timezoneID rangeOfString:@"/"]; if (range.location != NSNotFound) { timezoneID = [timezoneID substringWithRange:NSMakeRange(range.location+1, timezoneID.length-1 - range.location)]; } return timezoneID; } else { return @"Error"; } } - (NSString *)getTimeForTimeZoneWithFutureSliderValue:(NSInteger)futureSliderValue { NSCalendar *currentCalendar = [NSCalendar autoupdatingCurrentCalendar]; NSDate *newDate = [currentCalendar dateByAddingUnit:NSCalendarUnitMinute value:futureSliderValue toDate:[NSDate date] options:kNilOptions]; NSDateFormatter *dateFormatter = [NSDateFormatter new]; dateFormatter.dateStyle = kCFDateFormatterNoStyle; NSNumber *is24HourFormatSelected = [[NSUserDefaults standardUserDefaults] objectForKey:CL24hourFormatSelectedKey]; dateFormatter.dateFormat = is24HourFormatSelected.boolValue ? @"HH:mm" : @"hh:mm a"; dateFormatter.timeZone = [NSTimeZone timeZoneWithName:self.timezoneID]; //In the format 22:10 return [dateFormatter stringFromDate:newDate]; } - (void)retrieveLatitudeAndLongitudeWithSearchString:(NSString *)formattedString { NSString *preferredLanguage = [NSLocale preferredLanguages][0]; if (![CLAPIConnector isUserConnectedToInternet]) { /*Show some kind of information label*/ return; } NSArray* words = [formattedString componentsSeparatedByCharactersInSet :[NSCharacterSet whitespaceAndNewlineCharacterSet]]; formattedString = [words componentsJoinedByString:CLEmptyString]; NSString *urlString = [NSString stringWithFormat:CLLocationSearchURL, formattedString, preferredLanguage]; [CLAPIConnector dataTaskWithServicePath:urlString bySender:self withCompletionBlock:^(NSError *error, NSDictionary *json) { dispatch_async(dispatch_get_main_queue(), ^{ if (error || [json[@"status"] isEqualToString:@"ZERO_RESULTS"]) { return; } [json[@"results"] enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull dictionary, NSUInteger idx, BOOL * _Nonnull stop) { if ([dictionary[CLPlaceIdentifier] isEqualToString:self.place_id]) { //We have a match NSDictionary *latLang = dictionary[@"geometry"][@"location"]; self.latitude = [NSString stringWithFormat:@"%@", latLang[@"lat"]]; self.longitude = [NSString stringWithFormat:@"%@", latLang[@"lng"]]; } }]; }); }]; } - (NSString *)getLocalCurrentDate { NSDateFormatter *dateFormatter = [NSDateFormatter new]; dateFormatter.dateStyle = kCFDateFormatterShortStyle; dateFormatter.timeStyle = kCFDateFormatterNoStyle; dateFormatter.timeZone = [NSTimeZone systemTimeZone]; return [NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterNoStyle]; } - (NSString *)compareSystemDate:(NSString *)systemDate toTimezoneDate:(NSString *)date { NSDateFormatter *formatter = [NSDateFormatter new]; formatter.dateFormat = [NSDateFormatter dateFormatFromTemplate:@"MM/dd/yyyy" options:0 locale:[NSLocale currentLocale]]; NSDate *localDate = [formatter dateFromString:systemDate]; NSDate *timezoneDate = [formatter dateFromString:date]; // Specify which units we would like to use NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar]; NSInteger weekday = [calendar component:NSCalendarUnitWeekday fromDate:localDate]; if ([self.nextUpdate isKindOfClass:[NSString class]]) { NSUInteger units = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay; NSDateComponents *comps = [[NSCalendar currentCalendar] components:units fromDate:timezoneDate]; comps.day = comps.day + 1; NSDate *tomorrowMidnight = [[NSCalendar currentCalendar] dateFromComponents:comps]; CLTimezoneData *newDataObject = [CLTimezoneData new]; newDataObject.timezoneID = self.timezoneID; newDataObject.formattedAddress = self.formattedAddress; newDataObject.latitude = self.latitude; newDataObject.longitude = self.longitude; newDataObject.customLabel = self.customLabel; newDataObject.place_id = self.place_id; newDataObject.nextUpdate = tomorrowMidnight; newDataObject.isFavourite = @(NSOffState); PanelController *panelController = [PanelController getPanelControllerInstance]; (panelController.defaultPreferences)[[panelController.defaultPreferences indexOfObject:self]] = newDataObject; [[NSUserDefaults standardUserDefaults] setObject:panelController.defaultPreferences forKey:CLDefaultPreferenceKey]; } NSInteger daysApart = [timezoneDate daysFrom:localDate]; if (daysApart == 0) { return @"Today"; } else if (daysApart == -1) { return @"Yesterday"; } else if (daysApart == 1) { return @"Tomorrow"; } else { return [self getWeekdayFromInteger:weekday+2]; } } - (NSString *)getDateForTimeZoneWithFutureSliderValue:(NSInteger)futureSliderValue andDisplayType:(CLDateDisplayType)type { NSCalendar *currentCalendar = [NSCalendar autoupdatingCurrentCalendar]; NSDate *newDate = [currentCalendar dateByAddingUnit:NSCalendarUnitMinute value:futureSliderValue toDate:[NSDate date] options:kNilOptions]; NSDateFormatter *dateFormatter = [NSDateFormatter new]; dateFormatter.dateStyle = kCFDateFormatterShortStyle; dateFormatter.timeStyle = kCFDateFormatterNoStyle; dateFormatter.timeZone = [NSTimeZone timeZoneWithName:self.timezoneID]; NSNumber *relativeDayPreference = [[NSUserDefaults standardUserDefaults] objectForKey:CLRelativeDateKey]; if (relativeDayPreference.integerValue == 0 && type == CLPanelDisplay) { return [self compareSystemDate:[self getLocalCurrentDate] toTimezoneDate:[dateFormatter stringFromDate:newDate]]; } else { NSDateFormatter *formatter = [NSDateFormatter new]; formatter.dateFormat = [NSDateFormatter dateFormatFromTemplate:@"MM/dd/yyyy" options:0 locale:[NSLocale currentLocale]]; NSDate *convertedDate = [formatter dateFromString:[dateFormatter stringFromDate:newDate]]; NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar]; NSInteger weekday = [calendar component:NSCalendarUnitWeekday fromDate:convertedDate]; return [self getWeekdayFromInteger:weekday]; } } - (NSString *)getWeekdayFromInteger:(NSInteger)weekdayInteger { if (weekdayInteger > 7) { weekdayInteger = weekdayInteger - 7; } switch (weekdayInteger) { case 1: return @"Sunday"; break; case 2: return @"Monday"; break; case 3: return @"Tuesday"; break; case 4: return @"Wednesday"; break; case 5: return @"Thursday"; break; case 6: return @"Friday"; break; case 7: return @"Saturday"; break; default: return @"Error"; break; } } - (NSString *)getMenuTitle { NSMutableString *menuTitle = [NSMutableString new]; NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; NSNumber *shouldCityBeShown = [userDefaults objectForKey:CLShowPlaceInMenu]; NSNumber *shouldDayBeShown = [userDefaults objectForKey:CLShowDayInMenu]; NSNumber *shouldDateBeShown = [userDefaults objectForKey:CLShowDateInMenu]; if (shouldCityBeShown.boolValue == 0) { self.customLabel.length > 0 ? [menuTitle appendString:self.customLabel] : [menuTitle appendString:self.formattedAddress]; } if (shouldDayBeShown.boolValue == 0) { NSString *substring = [self getDateForTimeZoneWithFutureSliderValue:0 andDisplayType:CLMenuDisplay]; substring = [substring substringToIndex:3]; if (menuTitle.length > 0) { [menuTitle appendFormat:@" %@",substring.capitalizedString]; } else { [menuTitle appendString:substring.capitalizedString]; } } if (shouldDateBeShown.boolValue == 0) { NSString *date = [[NSDate date] formattedDateWithFormat:@"MMM dd" timeZone:[NSTimeZone timeZoneWithName:self.timezoneID] locale:[NSLocale currentLocale]]; if (menuTitle.length > 0) { [menuTitle appendFormat:@" %@",date]; } else { [menuTitle appendString:date]; } } menuTitle.length > 0 ? [menuTitle appendFormat:@" %@",[self getTimeForTimeZoneWithFutureSliderValue:0]] : [menuTitle appendString:[self getTimeForTimeZoneWithFutureSliderValue:0]]; return menuTitle; } -(void)initializeSunriseSunsetWithSliderValue:(NSInteger)sliderValue { if (!self.latitude || !self.longitude) { //Retrieve the values using Google Places API if (self.selectionType == CLTimezoneSelection) { /* A timezone has been selected*/ NSLog(@"%@", self); return; } [self retrieveLatitudeAndLongitudeWithSearchString:self.formattedAddress]; } EDSunriseSet *sunriseSetObject = [EDSunriseSet sunrisesetWithDate:[[NSCalendar autoupdatingCurrentCalendar] dateByAddingUnit:NSCalendarUnitMinute value:sliderValue toDate:[NSDate date] options:kNilOptions] timezone:[NSTimeZone timeZoneWithName:self.timezoneID] latitude:self.latitude.doubleValue longitude:self.longitude.doubleValue]; self.sunriseTime = sunriseSetObject.sunrise; self.sunsetTime = sunriseSetObject.sunset; } -(NSString *)getFormattedSunriseOrSunsetTimeAndSliderValue:(NSInteger)sliderValue { /* We have to call this everytime so that we get an updated value everytime! */ [self initializeSunriseSunsetWithSliderValue:sliderValue]; if (!self.sunriseTime && !self.sunsetTime) { return CLEmptyString; } self.sunriseOrSunset = [self.sunriseTime isLaterThanOrEqualTo:[NSDate date]]; NSDate *newDate = self.sunriseOrSunset ? self.sunriseTime : self.sunsetTime; NSDateFormatter *dateFormatter = [NSDateFormatter new]; dateFormatter.dateStyle = kCFDateFormatterNoStyle; dateFormatter.timeZone = [NSTimeZone timeZoneWithName:self.timezoneID]; NSNumber *is24HourFormatSelected = [[NSUserDefaults standardUserDefaults] objectForKey:CL24hourFormatSelectedKey]; dateFormatter.dateFormat = is24HourFormatSelected.boolValue ? @"HH:mm" : @"hh:mm a"; //In the format 22:10 return [dateFormatter stringFromDate:newDate]; } - (void)save { NSArray *defaultPreference = [[NSUserDefaults standardUserDefaults] objectForKey:CLDefaultPreferenceKey]; if (defaultPreference == nil) { defaultPreference = [NSMutableArray new]; } NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:self]; NSMutableArray *newArray = [[NSMutableArray alloc] initWithArray:defaultPreference]; [newArray addObject:encodedObject]; [[NSUserDefaults standardUserDefaults] setObject:newArray forKey:CLDefaultPreferenceKey]; } @end