#import "SapphireEpisode.h" #import "SapphireSeason.h" #import "SapphireSubEpisode.h" #import "SapphireMediaPreview.h" #import "SapphireFileMetaData.h" #import "SapphireMetaDataSupport.h" #import "SapphireXMLEpisodeData.h" #import "SapphireXMLData.h" #import "SapphireApplianceController.h" @implementation SapphireEpisode + (SapphireEpisode *)episode:(int)ep inSeason:(int)season forShow:(NSString *)show withPath:(NSString *)showPath inContext:(NSManagedObjectContext *)moc { SapphireSeason *tvseason = [SapphireSeason season:season forShow:show withPath:showPath inContext:moc]; NSEnumerator *epEnum = [tvseason.episodesSet objectEnumerator]; SapphireEpisode *tvep; while((tvep = [epEnum nextObject]) != nil) { if([SapphireSubEpisode subEpisode:ep inEpisode:tvep] != nil) return tvep; } SapphireEpisode *ret = [NSEntityDescription insertNewObjectForEntityForName:SapphireEpisodeName inManagedObjectContext:moc]; ret.season = tvseason; ret.tvShow = tvseason.tvShow; [ret addSubEpisodesObject:[SapphireSubEpisode createSubEpisode:ep inEpisode:ret]]; return ret; } + (SapphireEpisode *)episodeTitle:(NSString *)title inSeason:(int)season forShow:(NSString *)show withPath:(NSString *)showPath inContext:(NSManagedObjectContext *)moc { SapphireSeason *tvseason = [SapphireSeason season:season forShow:show withPath:showPath inContext:moc]; NSEnumerator *epEnum = [tvseason.episodesSet objectEnumerator]; SapphireEpisode *tvep; while((tvep = [epEnum nextObject]) != nil) { if([SapphireSubEpisode subEpisodeTitle:title inEpisode:tvep] != nil) return tvep; } SapphireEpisode *ret = [NSEntityDescription insertNewObjectForEntityForName:SapphireEpisodeName inManagedObjectContext:moc]; ret.season = tvseason; ret.tvShow = tvseason.tvShow; [ret addSubEpisodesObject:[SapphireSubEpisode createSubEpisodeTitle:title inEpisode:ret]]; return ret; } - (void) dealloc { [sortedSubEpisodes release]; [super dealloc]; } - (void)createSortedEpisodes { if(sortedSubEpisodes != nil) return; NSArray *unsorted = [self.subEpisodesSet allObjects]; sortedSubEpisodes = [[unsorted sortedArrayUsingSelector:@selector(compare:)] retain]; } - (void)insertDictionary:(NSDictionary *)dict { SapphireSubEpisode *sub = [self.subEpisodesSet anyObject]; int secondEp = [[dict objectForKey:META_EPISODE_2_NUMBER_KEY] intValue]; int setIndex = -1; if(secondEp != 0) setIndex = 0; [sub insertDictionary:dict epIndex:setIndex]; if(secondEp != 0) { SapphireSubEpisode *sub = [SapphireSubEpisode createSubEpisode:secondEp inEpisode:self]; [sub insertDictionary:dict epIndex:1]; [self addSubEpisodesObject:sub]; } else [self.subEpisodesSet setSet:[NSSet setWithObject:sub]]; } + (SapphireEpisode *)episodeWithDictionary:(NSDictionary *)dict inContext:(NSManagedObjectContext *)moc { NSString *show = [dict objectForKey:META_SHOW_NAME_KEY]; int season = [[dict objectForKey:META_SEASON_NUMBER_KEY] intValue]; int ep = [[dict objectForKey:META_EPISODE_NUMBER_KEY] intValue]; if(show == nil || season == 0) return nil; NSString *showPath = [dict objectForKey:META_SHOW_IDENTIFIER_KEY]; SapphireEpisode *ret; if(ep == 0) { NSString *title = [dict objectForKey:META_TITLE_KEY]; ret = [SapphireEpisode episodeTitle:title inSeason:season forShow:show withPath:showPath inContext:moc]; } else ret = [SapphireEpisode episode:ep inSeason:season forShow:show withPath:showPath inContext:moc]; [ret insertDictionary:dict]; return ret; } - (NSNumber *)episodeNumber { overrideWithXMLForKey(SapphireXMLEpisodeData, NSNumber, episodeNumber); [self createSortedEpisodes]; return ((SapphireSubEpisode *)[sortedSubEpisodes objectAtIndex:0]).episodeNumber; } - (int)episodeNumberValue { return [[self episodeNumber] intValue]; } - (NSNumber *)lastEpisodeNumber { overrideWithXMLForKey(SapphireXMLEpisodeData, NSNumber, lastEpisodeNumber); [self createSortedEpisodes]; return ((SapphireSubEpisode *)[sortedSubEpisodes objectAtIndex:sortedSubEpisodes.count - 1]).episodeNumber; } - (int)lastEpisodeNumberValue { return [[self lastEpisodeNumber] intValue]; } - (NSNumber *)absoluteEpisodeNumber { overrideWithXMLForKey(SapphireXMLEpisodeData, NSNumber, absoluteEpisodeNumber); [self createSortedEpisodes]; return ((SapphireSubEpisode *)[sortedSubEpisodes objectAtIndex:0]).absoluteEpisodeNumber; } - (int)absoluteEpisodeNumberValue { return [[self absoluteEpisodeNumber] intValue]; } - (NSString *)episodeTitle { overrideWithXMLForKey(SapphireXMLEpisodeData, NSString, xml.title); [self createSortedEpisodes]; NSMutableArray *subs = [[sortedSubEpisodes valueForKey:@"episodeTitle"] mutableCopy]; [subs removeObject:[NSNull null]]; NSString *ret = [subs componentsJoinedByString:@" / "]; [subs release]; return ret; } - (NSString *)episodeDescription { overrideWithXMLForKey(SapphireXMLEpisodeData, NSString, xml.contentDescription); [self createSortedEpisodes]; NSMutableArray *subs = [[sortedSubEpisodes valueForKey:@"episodeDescription"] mutableCopy]; [subs removeObject:[NSNull null]]; NSString *ret = [subs componentsJoinedByString:@" / "]; [subs release]; return ret; } - (NSComparisonResult)compare:(SapphireEpisode *)other { NSComparisonResult result = [self.season compare:other.season]; if(result != NSOrderedSame) return result; NSNumber *myNumber = [self episodeNumber]; NSNumber *theirNumber = [other episodeNumber]; if([myNumber intValue] == 0 || [theirNumber intValue] == 0) return [self airDateCompare:other]; return [myNumber compare:theirNumber]; } - (NSDate *)airDate { [self createSortedEpisodes]; return ((SapphireSubEpisode *)[sortedSubEpisodes objectAtIndex:0]).airDate; } - (NSComparisonResult)airDateCompare:(SapphireEpisode *)other { return [[self airDate] compare:[other airDate]]; } - (void)insertDisplayMetaData:(NSMutableDictionary *)dict { id value = [self episodeTitle]; if(value != nil) [dict setObject:value forKey:META_TITLE_KEY]; value = [self episodeDescription]; if(value != nil) [dict setObject:value forKey:META_DESCRIPTION_KEY]; value = [[sortedSubEpisodes objectAtIndex:0] airDate]; if(value != nil) [dict setObject:value forKey:META_SHOW_AIR_DATE]; int season = [[self season] seasonNumberValue]; int ep = [self episodeNumberValue]; if(season != 0) [dict setObject:[[self season] seasonNumber] forKey:BRLocalizedString(META_SEASON_NUMBER_KEY, @"Season in metadata display")]; if(ep != 0) [dict setObject:[NSNumber numberWithInt:ep] forKey:BRLocalizedString(META_EPISODE_NUMBER_KEY, @"Epsiode in metadata display")]; if(ep != 0 && season != 0) { int lastEp = [self lastEpisodeNumberValue]; NSString *key = BRLocalizedString(META_EPISODE_AND_SEASON_KEY, @"Season / Epsiode in metadata display"); if(lastEp != nil && lastEp != ep) [dict setObject:[NSString stringWithFormat:@"%@ - %d / %d-%d", [[self tvShow] name], season, ep, lastEp] forKey:key]; else [dict setObject:[NSString stringWithFormat:@"%@ - %d / %d", [[self tvShow] name], season, lastEp] forKey:key]; } } - (void)insertAdditionalEpisode:(NSDictionary *)dict { SapphireSubEpisode *sub = [SapphireSubEpisode createSubEpisode:[[dict objectForKey:META_EPISODE_NUMBER_KEY] intValue] inEpisode:self]; [sub insertDictionary:dict epIndex:-1]; [self addSubEpisodesObject:sub]; } - (NSString *)path { [self createSortedEpisodes]; return [[sortedSubEpisodes objectAtIndex:0] path]; } - (NSString *)coverArtPath { NSString *ret = [[SapphireMetaDataSupport collectionArtPath] stringByAppendingPathComponent:[self path]]; NSString *file = searchCoverArtExtForPath(ret); if(file == nil) return [self.season coverArtPath]; return ret; } - (NSNumber *)watched { NSSet *files = self.filesSet; if([files count] < 2) return [[files anyObject] watched]; NSArray *remain = [[files allObjects] filteredArrayUsingPredicate:[SapphireApplianceController unwatchedPredicate]]; if([remain count]) return [NSNumber numberWithBool:YES]; return [NSNumber numberWithBool:NO]; } - (NSNumber *)favorite { NSSet *files = self.filesSet; if([files count] < 2) return [[files anyObject] favorite]; NSArray *remain = [[files allObjects] filteredArrayUsingPredicate:[SapphireApplianceController favoritePredicate]]; if([remain count]) return [NSNumber numberWithBool:YES]; return [NSNumber numberWithBool:NO]; } /*Overrides*/ - (void)addSubEpisodes:(NSSet*)value_ { [sortedSubEpisodes release]; sortedSubEpisodes = nil; [super addSubEpisodes:value_]; } - (void)removeSubEpisodes:(NSSet*)value_ { [sortedSubEpisodes release]; sortedSubEpisodes = nil; [super removeSubEpisodes:value_]; } - (void)addSubEpisodesObject:(SapphireSubEpisode*)value_ { [sortedSubEpisodes release]; sortedSubEpisodes = nil; [super addSubEpisodesObject:value_]; } - (void)removeSubEpisodesObject:(SapphireSubEpisode*)value_ { [sortedSubEpisodes release]; sortedSubEpisodes = nil; [super removeSubEpisodesObject:value_]; } - (void)clearPredicateCache { [self.season clearPredicateCache]; } @end