//
//  BSDCAppDelegate.m
//  BathyScapheDataConverter
//
//  Created by 堀 昌樹 on 11/11/27.
//  Copyright (c) 2011年 __MyCompanyName__. All rights reserved.
//

#import "BSDCAppDelegate.h"

#import "BSCoreDataManager.h"
#import "SQLiteDB.h"
#import "DatabaseManager.h"
#import "BSCDProgressPanelController.h"


#import "BSBoardInformationObject.h"
#import "BSThreadInformationObject.h"
#import "BSFavoriteObject.h"
#import "BSBoardHistoryObject.h"


@implementation BSDCAppDelegate

@synthesize panel;
@synthesize session;
@synthesize startTime;
@synthesize window = _window;
@synthesize cdManager;

- (void)dealloc
{
    [super dealloc];
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
	// Insert code here to initialize your application
	self.cdManager = [BSCoreDataManager defaultManager];
	[DatabaseManager setupDatabase];
}


+ (NSURL *)bathyScapheSupportFolderURL
{
	return [NSURL fileURLWithPath:[self bathyScapheSupportFolderPath]];
}
+ (NSString *)bathyScapheSupportFolderPath
{
	static NSString *bathyscapheSupportFolderPath = nil;
	
	if(bathyscapheSupportFolderPath) return bathyscapheSupportFolderPath;
	
	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory,
														 NSUserDomainMask,
														 YES);
	if(!paths || [paths count] == 0) {
		NSLog(@"Could not find Application Support folder");
		exit(-1);
	}
	
	NSString *supportFolder = [paths objectAtIndex:0];
	if([supportFolder length] == 0) {
		NSLog(@"Could not find Application SUpport folder");
		exit(-2);
	}
	
	bathyscapheSupportFolderPath = [supportFolder stringByAppendingPathComponent:@"BathyScaphe"];
	[bathyscapheSupportFolderPath retain];
	
	return bathyscapheSupportFolderPath;
}


- (void)loggingIfNeeded
{
	SQLiteDB *db = [[DatabaseManager defaultManager]databaseForCurrentThread];
	if([db lastErrorID] != SQLITE_OK) {
		NSLog(@"%@", [db lastError]);
	}
}

- (void)updateTime
{
	NSDate *now = [NSDate dateWithTimeIntervalSinceNow:0.0];
	panel.progressTime = [NSDate dateWithTimeIntervalSince1970:[now timeIntervalSinceDate:startTime] - [[NSTimeZone systemTimeZone] secondsFromGMT]];
}

- (SQLiteReservedQuery *)sqlForInsertion
{
	static SQLiteReservedQuery *query = nil;
	
	if(query) return query;
	
	NSString *sql = [NSString stringWithFormat:@"INSERT INTO %@ ( %@, %@, %@, %@, %@, %@, %@, %@ ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?)",
		   ThreadInfoTableName,
		   BoardIDColumn, ThreadIDColumn, ThreadNameColumn, NumberOfAllColumn, NumberOfReadColumn, ModifiedDateColumn, ThreadStatusColumn,
		   IsDatOchiColumn];
	query = [[SQLiteReservedQuery alloc] initWithQuery:sql usingSQLiteDB:[[DatabaseManager defaultManager] databaseForCurrentThread]];
	return query;
}
- (SQLiteReservedQuery *)sqlForInsertFav
{
	static SQLiteReservedQuery *query = nil;
	if(query) return query;
	
	NSString *sql = [NSString stringWithFormat:@"INSERT INTO %@ (%@, %@) VALUES (?, ?);",
					 FavoritesTableName,
					 BoardIDColumn, ThreadIDColumn];
	query = [[SQLiteReservedQuery alloc] initWithQuery:sql usingSQLiteDB:[[DatabaseManager defaultManager] databaseForCurrentThread]];
	return query;
}
- (void)convertBoards:(NSArray *)boards
{
	DatabaseManager *dm = [DatabaseManager defaultManager];
    panel.message = @"Converting board informations ...";
	panel.amount = [boards count];
	for(BSBoardInformationObject *board in boards) {
		[self updateTime];
		if( ([NSApp runModalSession:session] != NSRunContinuesResponse) ) return;
		
		panel.count++;
		if(NSNotFound != [dm boardIDForURLString:board.boardURL]) {
			NSLog(@"Duplicate board url (%@)", board.boardURL);
			continue;
		}
		
		[dm registerBoardName:board.boardName URLString:board.boardURL];
	}
}

- (void)convertThreadsInBoards:(NSArray *)boards
{
	DatabaseManager *dm = [DatabaseManager defaultManager];
    panel.message = @"Converting thread informations ...";
	for(BSBoardInformationObject *board in boards) {
		[self updateTime];
		NSUInteger boardID = [dm boardIDForURLString:board.boardURL];
		NSSet *threads = board.threads;
		panel.amount = [threads count];
		for(BSThreadInformationObject *thread in threads) {
			if( ([NSApp runModalSession:session] != NSRunContinuesResponse) ) return;
			
			NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init];
			[self updateTime];
			panel.count++;
			panel.message = [NSString stringWithFormat:@"Converting thread informations ...\n%@", board.boardName];
			
			if( ([NSApp runModalSession:session] != NSRunContinuesResponse) ) {
				[pool2 release];
				return;
			}
			
			SQLiteReservedQuery *sqlForInsertion = [self sqlForInsertion];
			[sqlForInsertion cursorWithFormat:
			 F_Int F_NSString F_NSString F_NSNumberOfInt F_NSNumberOfInt F_NSNumberOfDouble F_NSNumberOfInt F_NSNumberOfInt,
			 boardID, thread.threadID,
			 thread.threadName, thread.numberOfAll, thread.numberOfRead,
			 thread.modifiedDate ? [NSNumber numberWithDouble:[thread.modifiedDate timeIntervalSince1970]] : nil,
			 thread.threadStatus,
			 thread.isDatOchi];
			
			if(thread.lastWrittenDate) {
				[dm setLastWriteDate:thread.lastWrittenDate
						   atBoardID:boardID
					threadIdentifier:thread.threadID];
			}
            
			// label
			if(thread.threadLabel) {
				[dm setLabel:[thread.threadLabel integerValue]
				   boardName:board.boardName
			threadIdentifier:thread.threadID];
			}
			
			[pool2 release];
		}
		panel.amount = 0;
		panel.count = 0;
	}
}

- (void)convertFavorites:(BSCoreDataManager *)cdm
{
    panel.message = @"Converting Favorites ...";
	DatabaseManager *dm = [DatabaseManager defaultManager];
	NSArray *favs = [cdm fetchDataForEntityName:@"Favorite"
									  predicate:nil];
	for(BSFavoriteObject *fav in favs) {
		[self updateTime];
//		NSLog(@"%@", fav.thread.board.boardName);
		NSUInteger boardID = [dm boardIDForURLString:fav.thread.board.boardURL];
		SQLiteReservedQuery *query = [self sqlForInsertFav];
		[query cursorWithFormat:F_Int F_NSNumberOfInt,
		 boardID, fav.thread.threadID];
	}
}

- (void)convertBoardHistories:(NSArray *)boards
{
	panel.message = @"Converting board histories ...";
	DatabaseManager *dm = [DatabaseManager defaultManager];
	NSString *sql = [NSString stringWithFormat:@"INSERT INTO %@ (%@, %@, %@) VALUES (?, ?, ?);",
					 BoardInfoHistoryTableName,
					 BoardIDColumn, BoardNameColumn, BoardURLColumn];
	SQLiteReservedQuery *query = [[SQLiteReservedQuery alloc] initWithQuery:sql
															  usingSQLiteDB:[[DatabaseManager defaultManager] databaseForCurrentThread]];
	for(BSBoardInformationObject *board in boards) {
		[self updateTime];
		NSUInteger boardID = [dm boardIDForURLString:board.boardURL];
		for(BSBoardHistoryObject *hist in board.histories) {
			[self updateTime];
			[query cursorWithFormat:F_Int F_NSString F_NSString,
			 boardID, hist.boardName, hist.boardURL];
			[self loggingIfNeeded];
		}
	}
	[query release];
}

- (void)doConvertToSQLite
{
	self.startTime = [NSDate dateWithTimeIntervalSinceNow:0.0];
	self.panel = [[[BSCDProgressPanelController alloc] init] autorelease];
	
	[self updateTime];
	panel.label = @"Convert from CoreData to SQLite data";
	panel.message = @"Converting data ...";
	
	self.session = [NSApp beginModalSessionForWindow:panel.window];
	
	if( ([NSApp runModalSession:session] != NSRunContinuesResponse) ) goto finish;
	
	BSCoreDataManager *cdm = [BSCoreDataManager defaultManager];
	NSArray *boards = [cdm fetchDataForEntityName:@"BoardInformation" predicate:nil];
	[self updateTime];
		
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	[self convertBoards:boards];
	panel.amount = 0;
	panel.count = 0;
	[pool release];
	[self updateTime];
	
	pool = [[NSAutoreleasePool alloc] init];
	[self convertBoardHistories:boards];
	panel.amount = 0;
	panel.count = 0;
	[pool release];
	[self updateTime];
	
	pool = [[NSAutoreleasePool alloc] init];
	[self convertThreadsInBoards:boards];
	panel.amount = 0;
	panel.count = 0;
	[pool release];
	[self updateTime];
	
	pool = [[NSAutoreleasePool alloc] init];
	[self convertFavorites:cdm];
	panel.amount = 0;
	panel.count = 0;
	[pool release];
	
finish:
	[NSApp endModalSession:session];
	[panel.window close];
	[panel release];
	
	NSDate *now = [NSDate dateWithTimeIntervalSinceNow:0.0];
	NSLog(@"Finish %@",  [NSDate dateWithTimeIntervalSince1970:[now timeIntervalSinceDate:startTime] - [[NSTimeZone systemTimeZone] secondsFromGMT]]);
}
- (IBAction)convertToSQLite:(id)sender
{
	SQLiteDB *db = [[DatabaseManager defaultManager] databaseForCurrentThread];
	[db beginTransaction];
	[self doConvertToSQLite];
	[db commitTransaction];
}
@end
