//
//  TableControllerForMenu.m
//  ArmorP3V1
//

#import "TableControllerForMenu.h"
#import "Repository.h"
#import "TableControllerForSkill.h"
#import "IProgress.h"
#import "PSProgressView.h"
#import "Repository.h"
#import "CreditViewController.h"
#import "SkillFukugo.h"
#import "PSTableModel.h"
#import "Engine.h"
#import "TableControllerForText.h"
#import "TableControllerForResult.h"
#import "TableControllerForSettingSub.h"
#import "SkillDB.h"
#import "SingleAlert.h"
#import "PSMutex.h"

@implementation TableControllerForMenu

@synthesize footerView = _footerView;
@synthesize engine = _engine;
@synthesize progress = _progress;

#define ROW_SKILLS     0
#define ROW_MAX        0

#define BUTTON_MIN        1
#define BUTTON_SEARCH     1
#define BUTTON_PLUSSEARCH 2
#define BUTTON_MAX        2

#define CONFIG_MIN           0
#define CONFIG_WEAPON_SLOT   0
#define CONFIG_SEARCH_MATOME 1
#define CONFIG_MAX           1


-(id)init
{
    self = [self initWithStyle:UITableViewStyleGrouped];
    if (self) {
    }
    return self;
}

-(void)dealloc
{
    [_engine release];
    [_progress release];
    [_footerView release];
    [super dealloc];
}

-(id)initWithStyle:(UITableViewStyle)style {
    self = [super initWithStyle:style];
    if (self) {
    }else {
        [[PSMutex mainMutex] raiseMemoryError];
    }
    [[PSMutex mainMutex] showMemoryAlertIfError];
    return self;
}

- (void)viewDidAppear:(BOOL)animated
{
//  [super viewDidAppear:animated];
    [self catchupValues];
    [self createDatas];
}

-(void)catchupValues
{
    if (self.model != nil) {
        [self updateScreen];
        
        Repository* repo = [Repository mainRepository];
        PSConfig* config = repo.config;
        PSTableModel* model = self.model;
        PSTableSection* sect = [model getSectionAtIndex: 1];
        PSTableElement* elem;
        
        elem = [sect.listElements objectAtIndex:CONFIG_WEAPON_SLOT];
        config.session.searchWeaponSlotCount = elem.valueOfInteger;
        
        elem = [sect.listElements objectAtIndex:CONFIG_SEARCH_MATOME];
        config.session.searchMatome = elem.valueOfInteger;
    }
}

-(void)updateScreen {
    if (self.model != nil) {
        Repository* repo = [Repository mainRepository];
        
        PSTableModel* model = self.model;
        PSTableSection* sect = [model getSectionAtIndex:1];
        PSTableElement* elem;
        
        PSTableModel* nextModel;
        PSTableElement* selectedElement;
        
        elem = [sect.listElements objectAtIndex:CONFIG_WEAPON_SLOT];
        nextModel = elem.nextModel;
        selectedElement = nextModel.selectedElement;
        elem.valueOfSummary = selectedElement.text;
        elem.valueOfInteger = selectedElement.valueOfInteger;
    }
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.navigationItem.title = @"防具スキル検索";

    //create a footer view on the bottom of the tabeview
    _footerView = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 1400, 200)];
    
    for(int i = BUTTON_MIN; i <= BUTTON_MAX; ++ i ){
        UIButton* button = [self createButton:i];
        [_footerView addSubview:button];
    }
    
    self.tableView.tableFooterView = _footerView;
}

-(UIButton *)createButton:(NSInteger)type {
    UIButton* button = nil;
    switch(type) {
        case BUTTON_SEARCH:
            button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            button.frame = CGRectMake(0, 0, 280, 40);
            button.tag = type;
            [button setTitle:@"検索" forState:UIControlStateNormal];
            button.backgroundColor = [UIColor clearColor];
            [button setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
            [button addTarget:self action:@selector(clickButton1:) forControlEvents:UIControlEventTouchUpInside];
            break;
        case BUTTON_PLUSSEARCH:
            button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            button.frame = CGRectMake(0, 50, 280, 40);
            button.tag = type;
            [button setTitle:@"追加スキル検索" forState:UIControlStateNormal];
            button.backgroundColor = [UIColor clearColor];
            [button setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
            [button addTarget:self action:@selector(clickButton2:) forControlEvents:UIControlEventTouchUpInside];
            break;
            /*
        case BUTTON_FULLSEARCH:
            button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            button.frame = CGRectMake(0, 50, 280, 40);
            button.tag = type;
            [button setTitle:@"検索(全防具)" forState:UIControlStateNormal];
            button.backgroundColor = [UIColor clearColor];
            [button setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
            [button addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside];
            break;
             */
    }
    return button;
}

-(void)callBackLoad1:(PSTableModel *)model {
    PSTableSection *sect = [model getSection:@"スキル" : TRUE]; 
    PSTableElement* elem = [[PSTableElement alloc]init];
    PSTableModel* nextModel;
    PSTableElement* elemsel;

    Repository* repository = [Repository mainRepository];
    SkillSet* skills = repository.config.session.searchSkills;
    elem.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    NSMutableString* message2 = [[NSMutableString alloc]init]; 
                          
    if (skills != nil && !skills.isZero) {
        NSMutableArray* array = [skills getNamedSkillNameForSearch];
        NSMutableString* buffer = [[NSMutableString alloc]init];
        //[buffer appendString:@"スキル="];
        for (int i = 0; i < array.count; ++ i) {
            NSString* str = [array objectAtIndex:i];
            [buffer appendString:@" "];
            [buffer appendString: str];
            [buffer appendString:@"\n"];
        }
        [array release];
        [message2 appendString:buffer];
        [buffer release];
    } else {
        [message2 appendString:@"タップして選択"];
    }

    elem.text = message2;
    [message2 release];

    [sect addElement: elem];
    [elem release];

    sect = [model getSection:@"オプション": TRUE];
    
    if (true) {
        elem = [[PSTableElement alloc]init];
        elem.text = @"武器スロ";
        elem.cellStyle = PS_CELL_SUMMARY;
        elem.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        elem.flgNextView = FLG_NEXT_ITEM;
        
        nextModel = [[PSTableModel alloc]init];
        
        [nextModel easyAddInteger: nil: @"スロ無し"  :0];
        [nextModel easyAddInteger: nil: @"最大1"    :1];
        [nextModel easyAddInteger: nil: @"最大2"    :2];
        [nextModel easyAddInteger: nil: @"最大3"    :3];
        [nextModel easyAddInteger: nil: @"装飾品無し":-1];
        
        elemsel = [nextModel easyFindByInteger: repository.config.session.searchWeaponSlotCount];
        elemsel.selected = TRUE;
        elem.valueOfSummary = elemsel.text;
        elem.nextModel = nextModel;
        [sect addElement: elem];
        [elem release];
        [nextModel release];
    }

    
    if (true) {
        elem = [[PSTableElement alloc]init];
        elem.text = @"まとめ検索";
        elem.cellStyle = PS_CELL_SWITCH;
        elem.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        elem.valueOfInteger = repository.config.session.searchMatome;
        [sect addElement: elem];
        [elem release];
    }
}

- (IBAction)doPageAbout:(UIButton*)sender {
    CreditViewController* creaditView = [[CreditViewController alloc]init];
    UIBarButtonItem *backBarButtonItem =
    [[UIBarButtonItem alloc] initWithTitle:@"戻る"
                                     style:UIBarButtonItemStyleBordered
                                    target:nil 
                                    action:nil];
    [self.navigationItem setBackBarButtonItem:backBarButtonItem];
    [backBarButtonItem release];        
    
    [self.navigationController pushViewController:creaditView animated:YES];
    [creaditView release];  
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0) {
        TableControllerForSkill* settingView = [[TableControllerForSkill alloc]init];
        UIBarButtonItem *backBarButtonItem =
        [[UIBarButtonItem alloc] initWithTitle:@"戻る"
                                         style:UIBarButtonItemStyleBordered
                                        target:nil
                                        action:nil];
        [self.navigationItem setBackBarButtonItem:backBarButtonItem];
        [backBarButtonItem release];
        
        [self.navigationController pushViewController:settingView animated:YES];
        [settingView release];  
    }else {
        
        PSTableSection* sect = [self.model getSectionAtIndex:indexPath.section];
        PSTableElement* elem = [sect.listElements objectAtIndex:indexPath.row];
        if (elem.flgNextView == FLG_NEXT_ITEM) {
            TableControllerForSettingSub* nextView = [TableControllerForSettingSub alloc];
            [nextView initWithData:elem];
            UIBarButtonItem *backBarButtonItem =
            [[UIBarButtonItem alloc] initWithTitle:@"戻る"
                                             style:UIBarButtonItemStyleBordered
                                            target:nil
                                            action:nil];
            [self.navigationItem setBackBarButtonItem:backBarButtonItem];
            [backBarButtonItem release];
            [self.navigationController pushViewController:nextView animated:YES];
            [nextView release];
        }
    }
}

- (IBAction)clickButton1:(UIButton*)sender {
    Repository* repo = [Repository mainRepository];

    PSTableElement* elem;
    Repository* repository = [Repository mainRepository];
    PSTableSection* sect = [self.model getSection:@"オプション": FALSE];
    
    elem = [sect.listElements objectAtIndex:CONFIG_WEAPON_SLOT];
    elem = [elem.nextModel selectedElement];
    repository.config.session.searchWeaponSlotCount = elem.valueOfInteger;
    
    repo.config.session.searchPlusAlpha = FALSE;
    [repo.config writeProperties];

	[self performSelectorInBackground:@selector(doProcess:) withObject:nil];
}

- (IBAction)clickButton2:(UIButton*)sender {
    Repository* repo = [Repository mainRepository];

    PSTableElement* elem;
    Repository* repository = [Repository mainRepository];
    PSTableSection* sect = [self.model getSection:@"オプション": FALSE];
    
    elem = [sect.listElements objectAtIndex:CONFIG_WEAPON_SLOT];
    elem = [elem.nextModel selectedElement];
    repository.config.session.searchWeaponSlotCount = elem.valueOfInteger;

    repo.config.session.searchPlusAlpha = TRUE;
    [repo.config writeProperties];

	[self performSelectorInBackground:@selector(doPlusAlpha:) withObject:nil];
}

- (void)doProcess:(id)none {
    @try {
        if ([[PSMutex mainMutex] tryEnterTask] == FALSE) {
            //[[PSMutex mainMutex] showStillWorkingAlert];
            return;
        }
        if ([PSMutex mainMutex].isHaveMemoryAlert) {
            [[PSMutex mainMutex] showMemoryAlertIfError];
            return;
        }
        Repository* repo = [Repository mainRepository];
        SkillFukugo* fukugo = repo.fukugo;
        self.progress = [[PSProgressView alloc]init];
        [self.progress showSheet: self.view: @"検索中"];
        
        SkillSet* skill0 = [repo.config.session.searchSkills canonical];
        NSMutableArray* skills = [[NSMutableArray alloc]init];
        [fukugo searchFilter:repo.config.session :skills : skill0];
        [skill0 release];
        
        PSSession* sess2 = [repo.config.session makeCopy];
        self.engine = nil;
        _engine = [[Engine alloc]initWithSession:sess2];
        
        for (int i = 0; i < skills.count; ++ i) {
            SkillSet* sk = [skills objectAtIndex:i];
            repo.config.session.searchSkills = sk;
            Engine* engine = [[Engine alloc]initWithSession:repo.config.session ];
            [engine pageActionScan:self.progress];
            [self.engine loadResult: engine];
            [engine release];
            
            [[PSMutex mainMutex] showMemoryAlertIfError];
        }
        
        sess2.searchSkills = skill0;
        
        if (self.progress.cancelFlag == FALSE || self.engine.listResultSearch.count > 0) {
            [self performSelectorOnMainThread:@selector(doNextPage:) withObject:_engine waitUntilDone:FALSE];
        }
        [skills release];
        [sess2 release];
    }
    @catch (NSException *exception) {
        NSLog(@"exception %@ %@", exception, [exception callStackSymbols]);
    }
    @finally {
        [[PSMutex mainMutex] endTask];
    }
}

- (void)doNextPage:(id)prev {
    @try {
        Engine* engine = prev;
        
        UIViewController* resultView = [[TableControllerForResult alloc]initWithData:engine];
        UIBarButtonItem *backBarButtonItem = 
        [[UIBarButtonItem alloc] initWithTitle:@"戻る"
                                         style:UIBarButtonItemStyleBordered
                                        target:nil 
                                        action:nil];
        [self.navigationItem setBackBarButtonItem:backBarButtonItem];
        [backBarButtonItem release];        
        
        [self.progress finish];
        self.progress = nil;

        [self.navigationController pushViewController:resultView animated:YES];
        [resultView release];
    }
    @catch (NSException *exception) {
        NSLog(@"exception %@ %@", exception, [exception callStackSymbols]);
    }
}

-(void)doPlusAlpha:(id)prev {
    SkillSet* newSkill = nil;
    @try {
        if ([[PSMutex mainMutex] tryEnterTask] == FALSE) {
            //[[PSMutex mainMutex] showStillWorkingAlert];
            return;
        }
        if ([PSMutex mainMutex].isHaveMemoryAlert) {
            [[PSMutex mainMutex] showMemoryAlertIfError];
            return;
        }
        if (self.progress == nil) {
            self.progress = [[PSProgressView alloc]init];
        }
        [self.progress createSub];
        [self.progress showSheet: self.view: @"追加発動スキル"];
        
        Repository* repo = [Repository mainRepository];
        SkillFukugo* fukugo = repo.fukugo;
        SkillSet* skill0 = [repo.config.session.searchSkills canonical];
        NSMutableArray* listSkills = [[NSMutableArray alloc]init];
        [fukugo searchFilter:repo.config.session :listSkills : skill0];
        [skill0 release];
        PSSession* session = repo.config.session;
        
        NSMutableDictionary* alreadyDone = [[NSMutableDictionary alloc]init];
        NSMutableSet* setResult = [[NSMutableSet alloc]init];
        
        NSMutableArray* baseEngineList = [[NSMutableArray alloc]init];
        NSMutableDictionary* listFailed = [[NSMutableDictionary alloc]init];
        NSMutableArray* seekList2 = [[NSMutableArray alloc]init];

        SkillDB* skillDB = repo.skillDB;
        
        for (int i = 0; i < skillDB.countOfCategory; ++ i) {
            SkillCategory* cate = [skillDB categoryOfIndex:i];
            for (int j = 0; j < cate.count; ++ j) {
                SkillPoint* pt = [cate pointAtIndex:cate.count - j - 1];
                if (pt.positiveRange && pt.skillPoint > 0) {
                    [seekList2 addObject: pt];
                }
            }
        }

        for (int i = 0; i < listSkills.count; ++ i) {
            SkillSet* skills = [listSkills objectAtIndex:i];
            
            [self.progress setLabelText:@"ready"];
            
            PSSession* search2 = [session makeCopy];
            search2.searchSkills = skills;
            search2.searchMaxCount = 1;
            
            self.engine = [[Engine alloc]initWithSession:search2];
            self.engine.useAnotherCheck = TRUE;
            
            if ([self.engine pageActionScan: self.progress]) {
                
            }else {
                break;
            }
            [alreadyDone removeObjectForKey:skills];
            [alreadyDone setObject:skills forKey:skills];
            [baseEngineList removeAllObjects];
            [baseEngineList addObject:self.engine];
            self.engine = nil;
            
            [listFailed removeAllObjects];
            
            for (int x = 0; x < baseEngineList.count; ++ x) {
                if (self.progress.cancelFlag) {
                    break;
                }
                
                Engine* baseEngine = [baseEngineList objectAtIndex: x];
                
                for (int i = 0; i < seekList2.count; ++ i) {
                    NSMutableString* str = [[NSMutableString alloc]init];
                    
                    SkillPoint* seek = [seekList2 objectAtIndex:i];
                    long px = x * seekList2.count + i;
                    long pe = baseEngineList.count * seekList2.count;
                    
                    SkillKind* kind = seek.skillKind;
                    [str appendFormat:@"追加発動 %@=%d", kind.name, seek.skillPoint];
                    
                    self.progress.percent = (float)px * 100.0 / pe;
                    self.progress.labelText = str;
                    [str release];
                    
                    newSkill = [[SkillSet alloc]init];
                    [newSkill set_all:skills];
                    
                    int skillX = [newSkill indexOfKind:seek.skillKind];
                    if (skillX >= 0) {
                        int pointX = newSkill.point[skillX];
                        BOOL rangeX = newSkill.positive[skillX];
                        if (rangeX) {
                            if (pointX >= seek.skillPoint) {
                                [newSkill release];
                                newSkill = nil;
                                continue;
                            }
                        }else {
                            if (pointX <= seek.skillPoint) {
                                [newSkill release];
                                newSkill = nil;
                                continue;
                            }
                        }
                    }
                    
                    [newSkill set:seek.skillKind :seek.skillPoint :seek.positiveRange];
                    if ([alreadyDone objectForKey:newSkill] != nil) {
                        [newSkill release];
                        newSkill = nil;
                        continue;
                    } else {
                        [alreadyDone removeObjectForKey:newSkill];
                        [alreadyDone setObject:newSkill forKey:newSkill];
                        //[newSkill release];
                        //newSkill = nil;
                    }

                    BOOL doSkip = FALSE;
                    if ([self alreadyFailed:newSkill :listFailed]) {
                        doSkip = TRUE;
                    }
                     
                    if (doSkip) {
                        [newSkill release];
                        newSkill = nil;
                        continue;
                    }
                    SkillSet* skill3 = [[SkillSet alloc]init];
                    [skill3 set_all: skills];
                    [skill3 set:seek.skillKind :seek.skillPoint :seek.positiveRange];
                    PSSession* search3 = [session makeCopy];
                    search3.searchMaxCount = 1;
                    search3.searchSkills = skill3;
                    [skill3 release];
                    
                    Engine* myEngine = [[Engine alloc]initWithSession:search3];
                    [search3 release];
                    myEngine.superEngine = baseEngine;
                    myEngine.useAnotherCheck = FALSE;

                    NSObject<IProgress>* sub = [self.progress createSub];
                    [myEngine pageActionScan:sub];

                    if (!self.progress.cancelFlag) {
                        if (myEngine.listResultSearch.count > 0) {
                            [setResult addObject: seek]; 
                        }else {
                            [listFailed removeObjectForKey:newSkill];
                            [listFailed setObject:newSkill forKey:newSkill];
                            [newSkill release];
                            newSkill = nil;
                        }
                    }
                    [myEngine release];
                    if (self.progress.cancelFlag) {
                        break;
                    }
                }
            }
        }
        [alreadyDone release];
        [baseEngineList release];
        [listFailed release];
        [seekList2 release];
        [listSkills release];

        NSMutableString* strText = [[NSMutableString alloc]init];
        int count = 0;
        for (int i = 0; i < skillDB.countOfCategory; ++ i) {
            SkillCategory* cate = [skillDB categoryOfIndex:i];
            for (int j = 0; j < cate.count; ++ j) {
                SkillPoint* point = [cate pointAtIndex:j];
                
                if ([setResult containsObject:point]) {
                    [strText appendFormat:@"%@\n", point.pointName];
                    count ++;
                }
            }
        }
        
        if (count == 0) {
            [strText appendString:@"なにも見当たらないようです"];
        }
        [self performSelectorOnMainThread:@selector(doNextTextPage:) withObject:strText waitUntilDone:TRUE];
        [strText release];
        [setResult release];
    }
    @catch (NSException *exception) {
        NSLog(@"exception %@ %@", exception, [exception callStackSymbols]);
    }
    @finally {
        [[PSMutex mainMutex] endTask];
    }
}

- (void)doNextTextPage:(id)str {
    @try {
        NSString* text = str;
        TableControllerForText* resultView = [[TableControllerForText alloc]initWithText:text];
        UIBarButtonItem *backBarButtonItem = 
        [[UIBarButtonItem alloc] initWithTitle:@"戻る"
                                         style:UIBarButtonItemStyleBordered
                                        target:nil 
                                        action:nil];
        [self.navigationItem setBackBarButtonItem:backBarButtonItem];
        [backBarButtonItem release];
        
        [self.progress finish];
        self.progress = nil;

        [self.navigationController pushViewController:resultView animated:YES];
        [resultView release];    
        [text release];
    }
    @catch (NSException *exception) {
        NSLog(@"exception %@ %@", exception, [exception callStackSymbols]);
    }
}

-(BOOL)alreadyFailed:(SkillSet *)slotSkill :(NSMutableSet *)listFailed {
    NSEnumerator* e = [listFailed objectEnumerator];
    while (TRUE) {
        SkillSet* failed = [e nextObject];
        if (failed == nil) {
            break;
        }
        BOOL hit = TRUE;
        BOOL nocolumn = FALSE;
        for (int x = 0; x < failed.count; ++ x) {
            SkillKind* kind = [failed.listKind objectAtIndex: x];
            BOOL positive = failed.positive[x];
            
            int targetX = [slotSkill indexOfKind:kind];
            if (targetX < 0) {
                nocolumn = TRUE;
                break;
            }
            
            int value1 = failed.point[x];
            int value2 = slotSkill.point[targetX];
            
            if (positive) {
                if (value1 > value2) {
                    hit = false;
                    break;
                }
            }else {
                if (value1 < value2) {
                    hit = false;
                    break;
                }
            }
        }
        if (nocolumn) {
            //System.out.println("nocolumn " + slotSkill +" failed " + failed);
        }
        else if(hit) {
            //System.out.println("true " + slotSkill +" failed " + failed);
            return TRUE;
        }
        else {
            //System.out.println("skip " + slotSkill +" failed " + failed);
        }
    }
    //System.out.println("false " + slotSkill +" failed " + listFailed);
    return FALSE;
}


@end