<commit_before>#import "Common.h"
#import "MapsAppDelegate.h"
#import "MWMAlertViewController.h"
#import "MWMFrameworkListener.h"
#import "MWMMapDownloaderDefaultDataSource.h"
#import "MWMMapDownloaderLargeCountryTableViewCell.h"
#import "MWMMapDownloaderPlaceTableViewCell.h"
#import "MWMMapDownloaderSubplaceTableViewCell.h"
#import "MWMMapDownloaderTableViewCell.h"
#import "MWMMapDownloaderViewController.h"
#import "MWMSegue.h"
#import "MWMStorage.h"
#import "Statistics.h"
#import "UIColor+MapsMeColor.h"

#include "Framework.h"

#include "storage/index.hpp"

extern NSString * const kCountryCellIdentifier = @"MWMMapDownloaderTableViewCell";
extern NSString * const kSubplaceCellIdentifier = @"MWMMapDownloaderSubplaceTableViewCell";
extern NSString * const kPlaceCellIdentifier = @"MWMMapDownloaderPlaceTableViewCell";
extern NSString * const kLargeCountryCellIdentifier = @"MWMMapDownloaderLargeCountryTableViewCell";

namespace
{
NSString * const kAllMapsLabelFormat = @"%@ %@ (%@)";
NSString * const kCancelActionTitle = L(@"cancel");
NSString * const kCancelAllTitle = L(@"downloader_cancel_all");
NSString * const kDeleteActionTitle = L(@"downloader_delete_map");
NSString * const kDownloaAllTitle = L(@"downloader_download_all_button");
NSString * const kDownloadActionTitle = L(@"downloader_download_map");
NSString * const kDownloadingTitle = L(@"downloader_downloading");
NSString * const kMapsTitle = L(@"downloader_maps");
NSString * const kShowActionTitle = L(@"zoom_to_country");
NSString * const kUpdateActionTitle = L(@"downloader_status_outdated");
} // namespace

@interface MWMBaseMapDownloaderViewController () <UIActionSheetDelegate, MWMFrameworkStorageObserver>

@property (weak, nonatomic) IBOutlet UITableView * tableView;

@property (weak, nonatomic) IBOutlet UIView * allMapsView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint * allMapsViewBottomOffset;
@property (weak, nonatomic) IBOutlet UIButton * allMapsButton;

@property (nonatomic) UIImage * navBarBackground;
@property (nonatomic) UIImage * navBarShadow;

@property (nonatomic) CGFloat lastScrollOffset;

@property (nonatomic) MWMMapDownloaderDataSource * dataSource;
@property (nonatomic) MWMMapDownloaderDefaultDataSource * defaultDataSource;

@property (nonatomic) NSMutableDictionary * offscreenCells;
@property (nonatomic) NSMutableDictionary<NSIndexPath *, NSNumber *> * cellHeightCache;

@property (nonatomic) BOOL skipCountryEventProcessing;
@property (nonatomic) BOOL forceFullReload;

@end

using namespace storage;

@implementation MWMBaseMapDownloaderViewController
{
  TCountryId m_actionSheetId;
}

- (void)viewDidLoad
{
  [super viewDidLoad];
  [self configNavBar];
  [self configTable];
  [self configAllMapsView];
}

- (void)viewWillAppear:(BOOL)animated
{
  [super viewWillAppear:animated];
  UINavigationBar * navBar = [UINavigationBar appearance];
  self.navBarBackground = [navBar backgroundImageForBarMetrics:UIBarMetricsDefault];
  self.navBarShadow = navBar.shadowImage;
  UIColor * searchBarColor = [UIColor primary];
  [navBar setBackgroundImage:[UIImage imageWithColor:searchBarColor]
               forBarMetrics:UIBarMetricsDefault];
  navBar.shadowImage = [[UIImage alloc] init];
  [MWMFrameworkListener addObserver:self];
}

- (void)viewWillDisappear:(BOOL)animated
{
  [super viewWillDisappear:animated];
  UINavigationBar * navBar = [UINavigationBar appearance];
  [navBar setBackgroundImage:self.navBarBackground forBarMetrics:UIBarMetricsDefault];
  navBar.shadowImage = self.navBarShadow;
  [MWMFrameworkListener removeObserver:self];
  [self notifyParentController];
}

- (void)configNavBar
{
  if (self.dataSource.isParentRoot)
  {
    self.title = L(@"download_maps");
  }
  else
  {
    NodeAttrs nodeAttrs;
    GetFramework().Storage().GetNodeAttrs(self.parentCountryId.UTF8String, nodeAttrs);
    self.title = @(nodeAttrs.m_nodeLocalName.c_str());
  }
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
  [self.cellHeightCache removeAllObjects];
}

- (void)notifyParentController
{
  NSArray<MWMViewController *> * viewControllers = [self.navigationController viewControllers];
  BOOL const goingTreeDeeper = ([viewControllers indexOfObject:self] != NSNotFound);
  if (goingTreeDeeper)
    return;
  MWMViewController * parentVC = viewControllers.lastObject;
  if ([parentVC isKindOfClass:[MWMBaseMapDownloaderViewController class]])
  {
    MWMBaseMapDownloaderViewController * downloaderVC = static_cast<MWMBaseMapDownloaderViewController *>(parentVC);
    [downloaderVC processCountryEvent:self.parentCountryId.UTF8String];
  }
}

#pragma mark - MWMFrameworkStorageObserver

- (void)processCountryEvent:(TCountryId const &)countryId
{
  if (self.skipCountryEventProcessing)
    return;

  for (MWMMapDownloaderTableViewCell * cell in self.tableView.visibleCells)
    [cell processCountryEvent:countryId];

  auto process = ^
  {
    [self configAllMapsView];
    [self reloadData];
  };

  if (countryId == self.parentCountryId.UTF8String)
  {
    process();
  }
  else
  {
    TCountriesVec childrenId;
    GetFramework().Storage().GetChildren(self.parentCountryId.UTF8String, childrenId);
    if (find(childrenId.cbegin(), childrenId.cend(), countryId) != childrenId.cend())
      process();
  }
}

- (void)processCountry:(TCountryId const &)countryId progress:(TLocalAndRemoteSize const &)progress
{
  for (MWMMapDownloaderTableViewCell * cell in self.tableView.visibleCells)<commit_msg>[ios] Updated map downloader event processing.<commit_after>#import "Common.h"
#import "MapsAppDelegate.h"
#import "MWMAlertViewController.h"
#import "MWMFrameworkListener.h"
#import "MWMMapDownloaderDefaultDataSource.h"
#import "MWMMapDownloaderLargeCountryTableViewCell.h"
#import "MWMMapDownloaderPlaceTableViewCell.h"
#import "MWMMapDownloaderSubplaceTableViewCell.h"
#import "MWMMapDownloaderTableViewCell.h"
#import "MWMMapDownloaderViewController.h"
#import "MWMSegue.h"
#import "MWMStorage.h"
#import "Statistics.h"
#import "UIColor+MapsMeColor.h"

#include "Framework.h"

#include "storage/index.hpp"

extern NSString * const kCountryCellIdentifier = @"MWMMapDownloaderTableViewCell";
extern NSString * const kSubplaceCellIdentifier = @"MWMMapDownloaderSubplaceTableViewCell";
extern NSString * const kPlaceCellIdentifier = @"MWMMapDownloaderPlaceTableViewCell";
extern NSString * const kLargeCountryCellIdentifier = @"MWMMapDownloaderLargeCountryTableViewCell";

namespace
{
NSString * const kAllMapsLabelFormat = @"%@ %@ (%@)";
NSString * const kCancelActionTitle = L(@"cancel");
NSString * const kCancelAllTitle = L(@"downloader_cancel_all");
NSString * const kDeleteActionTitle = L(@"downloader_delete_map");
NSString * const kDownloaAllTitle = L(@"downloader_download_all_button");
NSString * const kDownloadActionTitle = L(@"downloader_download_map");
NSString * const kDownloadingTitle = L(@"downloader_downloading");
NSString * const kMapsTitle = L(@"downloader_maps");
NSString * const kShowActionTitle = L(@"zoom_to_country");
NSString * const kUpdateActionTitle = L(@"downloader_status_outdated");
} // namespace

@interface MWMBaseMapDownloaderViewController () <UIActionSheetDelegate, MWMFrameworkStorageObserver>

@property (weak, nonatomic) IBOutlet UITableView * tableView;

@property (weak, nonatomic) IBOutlet UIView * allMapsView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint * allMapsViewBottomOffset;
@property (weak, nonatomic) IBOutlet UIButton * allMapsButton;

@property (nonatomic) UIImage * navBarBackground;
@property (nonatomic) UIImage * navBarShadow;

@property (nonatomic) CGFloat lastScrollOffset;

@property (nonatomic) MWMMapDownloaderDataSource * dataSource;
@property (nonatomic) MWMMapDownloaderDefaultDataSource * defaultDataSource;

@property (nonatomic) NSMutableDictionary * offscreenCells;
@property (nonatomic) NSMutableDictionary<NSIndexPath *, NSNumber *> * cellHeightCache;

@property (nonatomic) BOOL skipCountryEventProcessing;
@property (nonatomic) BOOL forceFullReload;

@end

using namespace storage;

@implementation MWMBaseMapDownloaderViewController
{
  TCountryId m_actionSheetId;
}

- (void)viewDidLoad
{
  [super viewDidLoad];
  [self configNavBar];
  [self configTable];
  [self configAllMapsView];
}

- (void)viewWillAppear:(BOOL)animated
{
  [super viewWillAppear:animated];
  UINavigationBar * navBar = [UINavigationBar appearance];
  self.navBarBackground = [navBar backgroundImageForBarMetrics:UIBarMetricsDefault];
  self.navBarShadow = navBar.shadowImage;
  UIColor * searchBarColor = [UIColor primary];
  [navBar setBackgroundImage:[UIImage imageWithColor:searchBarColor]
               forBarMetrics:UIBarMetricsDefault];
  navBar.shadowImage = [[UIImage alloc] init];
  [MWMFrameworkListener addObserver:self];
}

- (void)viewWillDisappear:(BOOL)animated
{
  [super viewWillDisappear:animated];
  UINavigationBar * navBar = [UINavigationBar appearance];
  [navBar setBackgroundImage:self.navBarBackground forBarMetrics:UIBarMetricsDefault];
  navBar.shadowImage = self.navBarShadow;
  [MWMFrameworkListener removeObserver:self];
  [self notifyParentController];
}

- (void)configNavBar
{
  if (self.dataSource.isParentRoot)
  {
    self.title = L(@"download_maps");
  }
  else
  {
    NodeAttrs nodeAttrs;
    GetFramework().Storage().GetNodeAttrs(self.parentCountryId.UTF8String, nodeAttrs);
    self.title = @(nodeAttrs.m_nodeLocalName.c_str());
  }
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
  [self.cellHeightCache removeAllObjects];
}

- (void)notifyParentController
{
  NSArray<MWMViewController *> * viewControllers = [self.navigationController viewControllers];
  BOOL const goingTreeDeeper = ([viewControllers indexOfObject:self] != NSNotFound);
  if (goingTreeDeeper)
    return;
  MWMViewController * parentVC = viewControllers.lastObject;
  if ([parentVC isKindOfClass:[MWMBaseMapDownloaderViewController class]])
  {
    MWMBaseMapDownloaderViewController * downloaderVC = static_cast<MWMBaseMapDownloaderViewController *>(parentVC);
    [downloaderVC processCountryEvent:self.parentCountryId.UTF8String];
  }
}

#pragma mark - MWMFrameworkStorageObserver

- (void)processCountryEvent:(TCountryId const &)countryId
{
  if (self.skipCountryEventProcessing)
    return;

  for (MWMMapDownloaderTableViewCell * cell in self.tableView.visibleCells)
    [cell processCountryEvent:countryId];

  BOOL needReload = NO;
  auto const & s = GetFramework().Storage();
  s.ForEachInSubtree(self.parentCountryId.UTF8String,
                     [&needReload, &countryId](TCountryId const & descendantId, bool groupNode)
                     {
                       needReload = needReload || countryId == descendantId;
                     });
  if (needReload)
  {
    [self configAllMapsView];
    [self reloadData];
  }
}

- (void)processCountry:(TCountryId const &)countryId progress:(TLocalAndRemoteSize const &)progress
{
  for (MWMMapDownloaderTableViewCell * cell in self.tableView.visibleCells)
{'fraction_non_alphanumeric': 0.10333633904418395, 'fraction_numerical': 0.0006311992786293959, 'mean_word_length': 6.783157894736842, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 69, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7060924', 'n_tokens_mistral': 3492, 'n_tokens_neox': 3326, 'n_words': 623}