<commit_before>//
//  SpCSearchViewController.m
//  SpeedyCrew
//
//  Created by <NAME> on 03/01/2014.
//  Copyright (c) 2014 <NAME>. All rights reserved.
//

#import "SpCSearchViewController.h"
#import "SpCSearchView.h"
#import "SpCResultView.h"
#import "SpCMapViewController.h"
#import "SpCAppDelegate.h"
#import "SpCDatabase.h"
#import "SpCData.h"
#include "Database.h"

@interface SpCSearchViewController ()
@property NSMutableArray* searches;
@end

@implementation SpCSearchViewController

// ----------------------------------------------------------------------------

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    //-dk:TODO verify if this can ever be called for a non-initial view
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    self.searches = [[NSMutableArray alloc] init];

    SpCAppDelegate* delegate = [SpCAppDelegate instance];
    __weak typeof(self) weakSelf = self;
    NSString* id = [NSString stringWithFormat:@"%@-SearchViewController", self.side];
    [delegate.data addListener:^(NSString* name, NSObject* object){ [weakSelf reloadSearches]; } withId: id];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    NSLog(@"%@-SearchView received memory warning", self.side);
}

// ----------------------------------------------------------------------------
#pragma mark - Navigation

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    UIButton* button = (UIButton*)sender;
    int tag = 0;
    for (UIView* parent = button.superview; parent != Nil; parent = parent.superview) {
        if (parent.tag != 0) {
            tag = (int)parent.tag;
            break;
        }
    }
    if (tag != 0) {
        SpCMapViewController* map = [segue destinationViewController];
        map.search = [self.searches objectAtIndex: tag - 1];
    }
}

// ----------------------------------------------------------------------------
// search bar handling
//-dk:TODO update a search with an existing ID and unlink the search upon clear

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    //-dk:TODO do something useful?
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
    SpCData* data = [SpCAppDelegate instance].data;
    [data addSearchWithText:searchBar.text forSide:self.side];
    [searchBar resignFirstResponder];

}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
    NSLog(@"search bar cancel button clicked");
}
   
// ----------------------------------------------------------------------------
#pragma mark - Table view data source

- (void)basicReloadSearches
{
    SpeedyCrew::Database* db = [SpCDatabase getDatabase];
    std::string side([self.side UTF8String]);
    std::vector<std::string> searches(db->queryColumn("select id from search where side='" + side + "'"));
    [self.searches removeAllObjects];
    for (std::vector<std::string>::const_iterator it(searches.begin()), end(searches.end()); it != end; ++it) {
        [self.searches addObject: [SpCSearchView makeWithId:[NSString stringWithFormat:@"%s", it->c_str()] andSide:self.side]];
    }
}

- (void)reloadSearches
{
    [self basicReloadSearches];
    [self.tableView reloadData];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tv
{
    if ([self.searches count] == 0) {
        [self basicReloadSearches];
    }
    return [self.searches count];
}

#if 0
- (UIView*)tableView:(UITableView*)tv viewForHeaderInSection:(NSInteger)section
{
    UITableViewCell* header = [tv dequeueReusableCellWithIdentifier:@"Header"];
    header.tag = section + 1;
    UIButton* expand = (UIButton*)[header viewWithTag: -1001];
    SpCSearchView* search = [self.searches objectAtIndex: section];
    [expand setTitle: (search.expanded? @"-": @"+") forState:UIControlStateNormal];

    SpeedyCrew::Database* db = [SpCDatabase getDatabase];
    std::string text = db->query<std::string>("select query from search where id='" + db->escape([search.id UTF8String]) + "';");
    UIButton* title = (UIButton*)[header viewWithTag: -1002];
    [title setTitle: [NSString stringWithFormat:@"%s", text.c_str()] forState:UIControlStateNormal];

    UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc]
                                          initWithTarget:self
                                                  action:@selector(onRemove:)];
    swipe.direction               = UISwipeGestureRecognizerDirectionLeft;
    swipe.numberOfTouchesRequired = 1;
    [header addGestureRecognizer:swipe];

    return header;
}
#endif

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    SpCSearchView* search = [self.searches objectAtIndex: section];
    int result = [search updateResults];
    return 1 + (search.expanded? result: 0);
}

- (void)onExpand: (id)sender
{
    UITapGestureRecognizer* gesture = (UITapGestureRecognizer*)sender;
    int section = gesture.view.tag;
    if (section < [self.searches count]) {
        SpCSearchView* search = [self.searches objectAtIndex: section];
        search.expanded = !search.expanded;
        [self.tableView reloadData];
    }
}

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)path
{
    SpCSearchView* search = [self.searches objectAtIndex: path.section];
    UITableViewCell* cell = nil;
    if (path.row == 0) {
        cell = [tv dequeueReusableCellWithIdentifier:@"Search"];
        cell.textLabel.text = search.title;

        cell.imageView.userInteractionEnabled = YES;
        cell.imageView.tag = path.section;
        UITapGestureRecognizer* tapped = [[UITapGestureRecognizer alloc] initWithTarget: self action: @selector(onExpand:)];
        tapped.numberOfTapsRequired = 1;
        [cell.imageView addGestureRecognizer:tapped];
        cell.imageView.image = [UIImage imageNamed:(search.expanded? @"Minus": @"Plus")];

        cell.tag = path.section;
        UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc]
                                              initWithTarget:self
                                                      action:@selector(onRemove:)];
        swipe.direction               = UISwipeGestureRecognizerDirectionLeft;
        swipe.numberOfTouchesRequired = 1;
        [cell addGestureRecognizer:swipe];

    }
    else {<commit_msg>added delete and delete confirmation.<commit_after>//
//  SpCSearchViewController.m
//  SpeedyCrew
//
//  Created by <NAME> on 03/01/2014.
//  Copyright (c) 2014 <NAME>. All rights reserved.
//

#import "SpCSearchViewController.h"
#import "SpCSearchView.h"
#import "SpCResultView.h"
#import "SpCMapViewController.h"
#import "SpCAppDelegate.h"
#import "SpCDatabase.h"
#import "SpCData.h"
#include "Database.h"

@interface SpCSearchViewController ()
@property NSMutableArray* searches;
@end

@implementation SpCSearchViewController

// ----------------------------------------------------------------------------

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    //-dk:TODO verify if this can ever be called for a non-initial view
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    self.searches = [[NSMutableArray alloc] init];

    SpCAppDelegate* delegate = [SpCAppDelegate instance];
    __weak typeof(self) weakSelf = self;
    NSString* id = [NSString stringWithFormat:@"%@-SearchViewController", self.side];
    [delegate.data addListener:^(NSString* name, NSObject* object){ [weakSelf reloadSearches]; } withId: id];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    NSLog(@"%@-SearchView received memory warning", self.side);
}

// ----------------------------------------------------------------------------
#pragma mark - Navigation

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    UIButton* button = (UIButton*)sender;
    int tag = 0;
    for (UIView* parent = button.superview; parent != Nil; parent = parent.superview) {
        if (parent.tag != 0) {
            tag = (int)parent.tag;
            break;
        }
    }
    if (tag != 0) {
        SpCMapViewController* map = [segue destinationViewController];
        map.search = [self.searches objectAtIndex: tag - 1];
    }
}

// ----------------------------------------------------------------------------
// search bar handling
//-dk:TODO update a search with an existing ID and unlink the search upon clear

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    //-dk:TODO do something useful?
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
    SpCData* data = [SpCAppDelegate instance].data;
    [data addSearchWithText:searchBar.text forSide:self.side];
    [searchBar resignFirstResponder];

}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
    NSLog(@"search bar cancel button clicked");
}
   
// ----------------------------------------------------------------------------
#pragma mark - Table view data source

- (void)basicReloadSearches
{
    SpeedyCrew::Database* db = [SpCDatabase getDatabase];
    std::string side([self.side UTF8String]);
    std::vector<std::string> searches(db->queryColumn("select id from search where side='" + side + "'"));
    [self.searches removeAllObjects];
    for (std::vector<std::string>::const_iterator it(searches.begin()), end(searches.end()); it != end; ++it) {
        [self.searches addObject: [SpCSearchView makeWithId:[NSString stringWithFormat:@"%s", it->c_str()] andSide:self.side]];
    }
}

- (void)reloadSearches
{
    [self basicReloadSearches];
    [self.tableView reloadData];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tv
{
    if ([self.searches count] == 0) {
        [self basicReloadSearches];
    }
    return [self.searches count];
}

#if 0
- (UIView*)tableView:(UITableView*)tv viewForHeaderInSection:(NSInteger)section
{
    UITableViewCell* header = [tv dequeueReusableCellWithIdentifier:@"Header"];
    header.tag = section + 1;
    UIButton* expand = (UIButton*)[header viewWithTag: -1001];
    SpCSearchView* search = [self.searches objectAtIndex: section];
    [expand setTitle: (search.expanded? @"-": @"+") forState:UIControlStateNormal];

    SpeedyCrew::Database* db = [SpCDatabase getDatabase];
    std::string text = db->query<std::string>("select query from search where id='" + db->escape([search.id UTF8String]) + "';");
    UIButton* title = (UIButton*)[header viewWithTag: -1002];
    [title setTitle: [NSString stringWithFormat:@"%s", text.c_str()] forState:UIControlStateNormal];

    UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc]
                                          initWithTarget:self
                                                  action:@selector(onRemove:)];
    swipe.direction               = UISwipeGestureRecognizerDirectionLeft;
    swipe.numberOfTouchesRequired = 1;
    [header addGestureRecognizer:swipe];

    return header;
}
#endif

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    SpCSearchView* search = [self.searches objectAtIndex: section];
    int result = [search updateResults];
    return 1 + (search.expanded? result: 0);
}

- (void)onExpand: (id)sender
{
    UITapGestureRecognizer* gesture = (UITapGestureRecognizer*)sender;
    int section = gesture.view.tag;
    if (section < [self.searches count]) {
        SpCSearchView* search = [self.searches objectAtIndex: section];
        search.expanded = !search.expanded;
        [self.tableView reloadData];
    }
}

// ----------------------------------------------------------------------------

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)path {
    return path.row? NO: YES;
}

- (void)tableView:(UITableView *)tableView
        commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
        forRowAtIndexPath:(NSIndexPath *)path {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        NSLog(@"deleting the search of section %d", path.section);
        if (path.section < [self.searches count]) {
            SpCSearchView* search = [self.searches objectAtIndex:path.section];
            SpCData* data = [SpCAppDelegate instance].data;
            [data deleteSearch:search.id];
        }    
    }
}

// ----------------------------------------------------------------------------

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)path
{
    SpCSearchView* search = [self.searches objectAtIndex: path.section];
    UITableViewCell* cell = nil;
    if (path.row == 0) {
        cell = [tv dequeueReusableCellWithIdentifier:@"Search"];
        cell.textLabel.text = search.title;

        cell.imageView.userInteractionEnabled = YES;
        cell.imageView.tag = path.section;
        UITapGestureRecognizer* tapped = [[UITapGestureRecognizer alloc] initWithTarget: self action: @selector(onExpand:)];
        tapped.numberOfTapsRequired = 1;
        [cell.imageView addGestureRecognizer:tapped];
        cell.imageView.image = [UIImage imageNamed:(search.expanded? @"Minus": @"Plus")];
    }
    else {
{'fraction_non_alphanumeric': 0.17653136531365313, 'fraction_numerical': 0.005092250922509225, 'mean_word_length': 2.8950847944811726, 'pattern_counts': {'":': 4, '<': 16, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4433770', 'n_tokens_mistral': 4269, 'n_tokens_neox': 3943, 'n_words': 819}