#import "ReservationController.h"
#import "ReservationItem.h"
#import "VH7PC.h"
#import "Recoder.h"


#define RECORD_WAIT				[[[[NSBundle mainBundle] infoDictionary] objectForKey:@"RecordMargin"] intValue]


enum {
	RES_TITLE_TAG		= 10,

	RES_YEAR_TAG		= 22,
	RES_MONTH_TAG		= 20,
	RES_DAY_TAG			= 21,

	RES_SUN_TAG			= 30,
	RES_MON_TAG			= 31,
	RES_TUE_TAG			= 32,
	RES_WED_TAG			= 33,
	RES_THU_TAG			= 34,
	RES_FRI_TAG			= 35,
	RES_SAT_TAG			= 36,

	RES_STIME_HOUR_TAG	= 40,
	RES_STIME_MIN_TAG	= 41,
	RES_ETIME_HOUR_TAG	= 42,
	RES_ETIME_MIN_TAG	= 43,

	RES_PRESET_TAG		= 50,

	RES_POWEROFF_TAG	= 70
};


@implementation ReservationController

- (void) recStart:(id)item {	
	//電源ON
	[vh7pc_ sendCommand:0 andValue:0];
	
	[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
	
	//BANDに
	[vh7pc_ sendCommand:2 andValue:0];
	
	//preset変更
	[vh7pc_ sendCommand:26 andValue:[(ReservationItem *)item preset]];

	[recoder_ recordWithName:[(ReservationItem *)item filename]];
}

- (void) recEnd:(id)item {
	[(Recoder *)recoder_ stop];
	if ([item autopower]) {
		[vh7pc_ sendCommand:1 andValue:0];
	}
	
	if ([(ReservationItem *)item week] == 0) {
		[reservations_ removeObject:item];
		[table_ reloadData];
	}
}

- (void) stopCheckTimer {
	NSDate			*now = [NSDate date];
	NSEnumerator	*enu = [reservations_ objectEnumerator];
	id				obj;
	
	while (obj = [enu nextObject]) {
		NSDate				*date = [obj prevStopDate];
		NSTimeInterval		ti = [date timeIntervalSinceDate:now];
		
		if (ti < 0 && ti >= -60) {
			[self recEnd:obj];
			break;
		}
	}
}

- (void) startCheckTimer {
	NSDate			*now = [NSDate date];
	NSEnumerator	*enu = [reservations_ objectEnumerator];
	id				obj;
	
	while (obj = [enu nextObject]) {
		NSDate				*date = [obj nextRecDate];
		NSTimeInterval		ti = [date timeIntervalSinceDate:now];
		
		if (ti <= 60 && ti > 0) {
			[self recStart:obj];
			break;
		}
	}
}

- (void) startTimerStart2 {
	[self startCheckTimer];

	if (startTimer_) {
		[startTimer_ invalidate];
	}
	startTimer_ = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(startCheckTimer) userInfo:nil repeats:YES];
}

- (void) stopTimerStart2 {
	[self stopCheckTimer];

	if (stopTimer_) {
		[stopTimer_ invalidate];
	}
	stopTimer_ = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(stopCheckTimer) userInfo:nil repeats:YES];
}

- (void) startTimer {
	NSCalendarDate			*now = [NSCalendarDate date];
	int						sec = [now secondOfMinute];
	NSTimeInterval			start, stop;
	
	start = (sec > (60 - RECORD_WAIT)) ? (60 - sec) + (60 - RECORD_WAIT) : (60 - RECORD_WAIT) - sec;
	stop = (sec < RECORD_WAIT) ? RECORD_WAIT - sec : (60 - sec) + RECORD_WAIT;
	
	[NSTimer scheduledTimerWithTimeInterval:start target:self selector:@selector(startTimerStart2) userInfo:nil repeats:NO];
	[NSTimer scheduledTimerWithTimeInterval:stop target:self selector:@selector(stopTimerStart2) userInfo:nil repeats:NO];
}

- (void) stopTimer {
	if (startTimer_) {
		[startTimer_ invalidate];
	}
	if (stopTimer_) {
		[stopTimer_ invalidate];
	}
	startTimer_ = nil;
	stopTimer_ = nil;
}

- (void) setSheetFromItem:(ReservationItem *)item {
	NSDictionary *dic = [item dictionary];
	NSEnumerator *enu = [[[addSheet_ contentView] subviews] objectEnumerator];
	id obj;
	
	/*
	NSCalendarDate *sdate = [NSCalendarDate 
		dateWithString:[NSString stringWithFormat:@"%d/%d/%d %d:%d", 
			[[dic objectForKey:RES_ITEM_YEAR_KEY] intValue], 
			[[dic objectForKey:RES_ITEM_MONTH_KEY] intValue], 
			[[dic objectForKey:RES_ITEM_DAY_KEY] intValue], 
			[[dic objectForKey:RES_ITEM_HOUR_KEY] intValue], 
			[[dic objectForKey:RES_ITEM_MINUTE_KEY] intValue]]
		calendarFormat:@"%Y/%m/%d %H:%M"];
	NSCalendarDate *edate = [[[NSCalendarDate alloc] initWithTimeInterval:[item length] sinceDate:sdate] autorelease];
	
	int ehour = [edate hourOfDay];
	int emin = [edate minuteOfHour];
	*/
	int emin = [[dic objectForKey:RES_ITEM_MINUTE_KEY] intValue] + [item length] / 60;
	int ehour = [[dic objectForKey:RES_ITEM_HOUR_KEY] intValue] + emin / 60;
	emin %= 60;

	while (obj = [enu nextObject]) {
		switch ([obj tag]) {
		case RES_TITLE_TAG:
			if ([item title]) [obj setStringValue:[item title]];
			break;
		case RES_YEAR_TAG:		
			[obj setIntValue:[[dic objectForKey:RES_ITEM_YEAR_KEY] intValue]];
			break;
		case RES_MONTH_TAG:		
			[obj setIntValue:[[dic objectForKey:RES_ITEM_MONTH_KEY] intValue]];
			break;
		case RES_DAY_TAG:			
			[obj setIntValue:[[dic objectForKey:RES_ITEM_DAY_KEY] intValue]];
			break;
		case RES_SUN_TAG:			
		case RES_MON_TAG:			
		case RES_TUE_TAG:			
		case RES_WED_TAG:			
		case RES_THU_TAG:			
		case RES_FRI_TAG:			
		case RES_SAT_TAG:	
			[obj setState:((([item week] >> ([obj tag] % 10)) & 0x01) ? NSOnState : NSOffState)];
			break;
		case RES_STIME_HOUR_TAG:	
			[obj setIntValue:[[dic objectForKey:RES_ITEM_HOUR_KEY] intValue]];
			break;
		case RES_STIME_MIN_TAG:	
			[obj setIntValue:[[dic objectForKey:RES_ITEM_MINUTE_KEY] intValue]];
			break;
		case RES_ETIME_HOUR_TAG:	
			[obj setIntValue:ehour];
			break;
		case RES_ETIME_MIN_TAG:	
			[obj setIntValue:emin];
			break;
		case RES_PRESET_TAG:	
			[obj setIntValue:[item preset]];
			break;
		case RES_POWEROFF_TAG:
			[obj setState:[item autopower]];
			break;
		default:
			break;
		}
	}
}

- (ReservationItem *) itemFromSheet {
	NSEnumerator *enu = [[[addSheet_ contentView] subviews] objectEnumerator];
	id obj;
	
	NSString *title = nil;
	int year = 0;
	UInt8 date[2];	memset(date, 0, 2 * sizeof(UInt8));
	UInt8 week = 0;
	UInt8 time[4];	memset(time, 0, 4 * sizeof(UInt8));
	int preset = 0;
	long length = 0;
	BOOL poff = NO;
	while (obj = [enu nextObject]) {
		int tag = [obj tag];
		
		switch (tag) {
		case RES_TITLE_TAG:
			title = [obj stringValue];
			break;
		case RES_YEAR_TAG:	
			year = [obj intValue];
			break;
		case RES_MONTH_TAG:		
		case RES_DAY_TAG:			
			date[tag % 10] = [obj intValue];
			break;
		case RES_SUN_TAG:			
		case RES_MON_TAG:			
		case RES_TUE_TAG:			
		case RES_WED_TAG:			
		case RES_THU_TAG:			
		case RES_FRI_TAG:			
		case RES_SAT_TAG:			
			if ([obj state] == NSOnState) {
				week |= (0x01 << (tag % 10));
			}
			break;
		case RES_STIME_HOUR_TAG:	
		case RES_STIME_MIN_TAG:	
		case RES_ETIME_HOUR_TAG:	
		case RES_ETIME_MIN_TAG:	
			time[tag % 10] = [obj intValue];
			break;
		case RES_PRESET_TAG:	
			preset = [obj intValue];
			break;
		case RES_POWEROFF_TAG:
			poff = [obj state] == NSOnState;
			break;
		default:
			break;
		}
	}
	
	if (preset > 40 || preset < 1) {
		return nil;
	}
	if (*(UInt32 *)time == 0 || ((UInt16 *)time)[0] - ((UInt16 *)time)[1] == 0) {
		return nil;
	}
	if (week == 0x00) {
		if (*(UInt16 *)date == 0 && year == 0) {
			return nil;
		}
	}
	
	length = 60 * (time[2] * 60 + time[3] - (time[0] * 60 + time[1]));
	if (length < 0) {
		return nil;
	}
	
	return [ReservationItem itemWithDictionary:
		[NSDictionary dictionaryWithObjectsAndKeys:
			title,									RES_ITEM_TITLE_KEY,
			[NSNumber numberWithInt:week],			RES_ITEM_WEEK_KEY,
			[NSNumber numberWithInt:year],			RES_ITEM_YEAR_KEY,
			[NSNumber numberWithInt:date[0]],		RES_ITEM_MONTH_KEY,
			[NSNumber numberWithInt:date[1]],		RES_ITEM_DAY_KEY,
			[NSNumber numberWithInt:time[0]],		RES_ITEM_HOUR_KEY,
			[NSNumber numberWithInt:time[1]],		RES_ITEM_MINUTE_KEY,
			[NSNumber numberWithInt:0],				RES_ITEM_SECOND_KEY,
			[NSNumber numberWithInt:preset],		RES_ITEM_PRESET_KEY,
			[NSNumber numberWithInt:0],				RES_ITEM_INPUT_KEY,
			[NSNumber numberWithLong:length],		RES_ITEM_INTERVAL_KEY,
			[NSNumber numberWithBool:poff],			RES_ITEM_POWEROFF_KEY,
			//self,									RES_ITEM_DELEGATE_KEY,
			nil
		]];
}

static id objstore__;

- (void)editend:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo {
	[sheet orderOut:self];
	if (returnCode) {
		id obj = objstore__;//[self itemFromSheet];
		//NSLog(@"item retaincount = %d", [obj retainCount]);
		if ((int)contextInfo < 0) {
			[reservations_ addObject:obj];
		} else {
			[[reservations_ objectAtIndex:(int)contextInfo] unregistTimer];
			[reservations_ replaceObjectAtIndex:(int)contextInfo withObject:obj];
		}
		[table_ reloadData];
	}
}


#pragma mark-


- (id) init {
	self = [super init];
	if (!self) return nil;
	
	reservations_ = [[NSMutableArray alloc] init];
	//timer_ = nil;
	
	return self;
}

- (void) awakeFromNib {
	[table_ setTarget:self];
	[table_ setDoubleAction:@selector(edit:)];
	
	[self startTimer];
}

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

- (NSArray *) array {
	NSMutableArray *res = [NSMutableArray arrayWithCapacity:[reservations_ count]];
	NSEnumerator *enu = [reservations_ objectEnumerator];
	id obj;
	
	while (obj = [enu nextObject]) {
		[res addObject:[obj dictionary]];
	}
	
	return res;
}

- (void) setArray:(NSArray *)ary {
	NSEnumerator *enu = [ary objectEnumerator];
	id obj;
	id tmp;
	
	while (obj = [enu nextObject]) {
		tmp = [ReservationItem itemWithDictionary:obj];
		if (tmp) [reservations_ addObject:tmp];
	}

	[table_ reloadData];
}

#pragma mark-


- (IBAction) edit:(id)sender {
	int	idx = [table_ selectedRow];
	
	if (idx >= 0) {
		[self setSheetFromItem:[reservations_ objectAtIndex:idx]];
	} else {
		return;
	}
	
	[NSApp 
		beginSheet:addSheet_ 
		modalForWindow:[table_ window] 
		modalDelegate:self 
		didEndSelector:@selector(editend:returnCode:contextInfo:) 
		contextInfo:(void *)idx];
}

- (IBAction) add:(id)sender {
	int idx = -1;
	[self setSheetFromItem:[ReservationItem item]];
	
	[NSApp 
		beginSheet:addSheet_ 
		modalForWindow:[table_ window] 
		modalDelegate:self 
		didEndSelector:@selector(editend:returnCode:contextInfo:) 
		contextInfo:(void *)idx];
}

- (IBAction) remove:(id)sender {
	int	idx = [table_ selectedRow];
	if (idx < 0) return; 

	[reservations_ removeObjectAtIndex:idx];
	[table_ reloadData];
}

- (IBAction) addok:(id)sender {
	if ([sender tag] % 10) {
		//OK
		objstore__ = [self itemFromSheet];
		//NSLog(@"objstore__ retaincount = %d", [objstore__ retainCount]);
		if (!objstore__) {
			//入力がおかしい
			NSBeep();
		} else {
			NSLog([[objstore__ dictionary] description]);
			[NSApp endSheet:addSheet_ returnCode:1];
		}
	} else {
		//Cancel
		[NSApp endSheet:addSheet_ returnCode:0];
	}
}

- (IBAction) weekButtonAction:(id)sender {
	NSEnumerator *enu = [[[addSheet_ contentView] subviews] objectEnumerator];
	id obj;
	BOOL b = [sender state] == NSOnState;
	
	while (obj = [enu nextObject]) {
		int tag = [obj tag];
		if (tag / 10 != 3) {
			continue;
		}
		
		if ([obj state] == NSOnState) {
			if (b) {
				if (obj != sender) return;
			} else {
				return;
			}
		}
	}
	
	[yearText_ setEnabled:!b];
	[yearFld_ setEnabled:!b];
	[monthText_ setEnabled:!b];
	[monthFld_ setEnabled:!b];
	[dayText_ setEnabled:!b];
	[dayFld_ setEnabled:!b];
}


#pragma mark-


- (int)numberOfRowsInTableView:(NSTableView *)aTableView {
	return [reservations_ count];
}

- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex {
	NSString *idt = [aTableColumn identifier];
	ReservationItem *item = [reservations_ objectAtIndex:rowIndex];
	
	if ([idt compare:@"Title"] == NSOrderedSame) {
		return [item title];
	} else if ([idt compare:@"Date"] == NSOrderedSame) {
		return [item dateString];
	} else if ([idt compare:@"Time"] == NSOrderedSame) {
		return [item timeString];
	} else if ([idt compare:@"Input"] == NSOrderedSame) {
		//return [NSNumber numberWithInt:[item input]];
		return @"Band";
	} else if ([idt compare:@"Preset"] == NSOrderedSame) {
		return [NSNumber numberWithInt:[item preset]];
	}
	
	return nil;
}

@end
