/* Copyright (c) 2004, Noah Sorscher
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 	¥ 	Redistributions of source code must retain the above copyright
 * 	notice, this list of conditions and the following disclaimer.
 * 	¥ 	Redistributions in binary form must reproduce the above copyright
 * 	notice, this list of conditions and the following disclaimer in the
 * 	documentation and/or other materials provided with the distribution.
 * 	¥ 	Neither the name of the Noah Sorscher nor the names of its
 * 	contributors may be used to endorse or promote products derived from
 * 	this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */
#import "tTracks.h"

@implementation tTracks


- (IBAction)open:(id)sender
{
    //[tracksWindow makeKeyAndOrderFront:nil];
    [controller setMainTabViewName:@"Tracks"];
    [self movieDidChangeTo:[controller currentMovie]];
    [self tableViewSelectionDidChange:nil];
}

- (void)textDidChange:(NSNotification *)aNotification
{
    //NSLog(@"textDidChange");
    if (recursion) return;
    NSTextView *box = [aNotification object];
    
    int col = [tracksTable editedColumn];
    if (col < 0) return;
    NSString *ident = [[[tracksTable tableColumns] objectAtIndex:col] identifier];
    if (![ident isEqualToString:@"Language"]) return;
    
    NSRange selection = [box selectedRange];
    NSString *string = [NSString stringWithString:[box string]];
    int initialLength = [string length];
    if (selection.location != initialLength) return;
    NSMutableArray *list = [NSMutableArray arrayWithArray:[tLanguages stringLangs]];
    [list addObject:@"Unspecified"];
    int i, n = [list count];
    recursion = YES;
    for (i=0;i<n;i++) {
        NSString *lang = [list objectAtIndex:i];
        if ([lang hasPrefix:string]) {
            lang = [lang substringFromIndex:initialLength];
            [box insertText:lang];
            selection.length = [lang length];
            [box setSelectedRange:selection];
            break;
        }
    }
    recursion = NO;
}

- (IBAction)delete:(id)sender
{
    if ([movie isOffline]) return;
    BOOL changed = NO;
    int i, n = [movie trackCount];
    TimeValue offset, lowOffset = [[movie trackAtIndex:0] offset];
    for (i=n-1;i>=0;i--) {
        if ([tracksTable isRowSelected:i]) {
            [[movie trackAtIndex:i] remove];
            changed = YES;
        } else {
            offset = [[movie trackAtIndex:i] offset];
            if (offset < lowOffset) lowOffset = offset;
        }
    }
    if (!changed) return;
    [movie setSaveInPlaceUnSafe];
    NSMovie *aMovie = movie;
    movie = nil;
    [self movieDidChangeTo:aMovie];
    if (lowOffset) {
        n = [movie trackCount];
        for (i=0;i<n;i++)
            [[movie trackAtIndex:i] setOffset:[[movie trackAtIndex:i] offset] - lowOffset];
    }
    [movie gatherData];
}

- (IBAction)alternateGroup:(id)sender
{
    if ([movie isOffline]) return;
    int i, n = [movie trackCount];
    NSMutableArray *selected = [NSMutableArray array];
    for (i=0;i<n;i++)
        if ([tracksTable isRowSelected:i])
            [selected addObject:[movie trackAtIndex:i]];
    if (![selected count])
        for (i=0;i<n;i++)
            if ([[movie trackAtIndex:i] isSoundType])
                [selected addObject:[movie trackAtIndex:i]];
    n = [selected count];
    if (n > 1) {
        MHTrack *lastTrack = nil, *thisTrack;
        for (i=0;i<n;i++) {
            thisTrack = [selected objectAtIndex:i];
            [lastTrack setAlternate:thisTrack];
            lastTrack = thisTrack;
        }
        [lastTrack setAlternate:[selected objectAtIndex:0]];
    }
}

- (void)movieDidChangeTo:(NSMovie *)aMovie
{
    //if (![tracksWindow isVisible]) return;
    movie = (MHMovie *)aMovie;
    if (!movie) return;
    [tracksTable reloadData];
}

- (void)awakeFromNib
{
    //NSLog(@"tTracks");
    didDelete = recursion = NO;
    [tracksTable setTarget:self];
    [tracksTable setDoubleAction:@selector(doubleClick)];
    [controller performSelector:@selector(addMovieChangeListener:) withObject:self afterDelay:0];
    [tracksTable registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
}

- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{	return [movie trackCount];	}

- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
    if (rowIndex >= [movie trackCount] || rowIndex < 0) return nil;
    MHTrack *track = [movie trackAtIndex:rowIndex];
    NSString *s = [aTableColumn identifier];
    if ([s isEqualToString:@"Name"]) {
        NSString *name = [track name];
        if (!name) name = [NSString stringWithFormat:@"%d %@ Track", rowIndex+1, [track type]];
        return name;
    } else if ([s isEqualToString:@"Enabled"]) return ([track enabled] ? @"YES" : @"NO");
    else if ([s isEqualToString:@"Offset"]) return [NSString stringWithFormat:@"%ld", [track offset]];
    else if ([s isEqualToString:@"Duration"]) return [NSString stringWithFormat:@"%ld", [track duration]];
    else if ([s isEqualToString:@"Language"]) return [track language];
    else if ([s isEqualToString:@"Type"]) return [track type];
    else if ([s isEqualToString:@"FourCC"]) return [track fourCC];
    else if ([s isEqualToString:@"Vendor"]) return [track vendor];
    else if ([s isEqualToString:@"Size"]) return [NSString stringWithFormat:@"%g", [track mbSize]];
    else if ([s isEqualToString:@"TimeScale"]) return [NSString stringWithFormat:@"%ld", [track timeScale]];
    else if ([s isEqualToString:@"Format"]) return [track format];
    else if ([s isEqualToString:@"Preload"]) return ([track preloads] ? @"YES" : @"NO");
    else if ([s isEqualToString:@"High Quality"]) return ([track highQuality] ? @"YES" : @"NO");
    else if ([s isEqualToString:@"Layer"]) return [NSString stringWithFormat:@"%d", [track layer]];
    else if ([s isEqualToString:@"Frame"]) return NSStringFromRect([track displayFrame]);
    return nil;
}

- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
    if (rowIndex >= [movie trackCount] || rowIndex < 0) return;
    if ([movie isOffline]) return;
    MHTrack *track = [movie trackAtIndex:rowIndex];
    NSString *s = [aTableColumn identifier];
    if ([s isEqualToString:@"Name"]) [track setName:anObject];
    else if ([s isEqualToString:@"Offset"]) [track setOffset:[anObject intValue]];
    else if ([s isEqualToString:@"Duration"]) [track setDuration:[anObject intValue]];
    else if ([s isEqualToString:@"FourCC"]) [track setFourCC:anObject];
    else if ([s isEqualToString:@"Vendor"]) [track setVendor:anObject];
    else if ([s isEqualToString:@"TimeScale"]) [track setTimeScale:[anObject intValue]];
    else if ([s isEqualToString:@"Format"]) [track setFormat:anObject];
    else if ([s isEqualToString:@"Layer"]) [track setLayer:(short)[anObject intValue]];
    else if ([s isEqualToString:@"Frame"]) [track setDisplayFrame:NSRectFromString(anObject)];
    else if ([s isEqualToString:@"Language"]) {
        [track setLanguage:anObject];
        [controller setCurrentMovie:movie];
    } else return;
    [movie setSaveInPlaceUnSafe];
    [movie gatherData];
}

- (NSString *)reduce:(NSString *)input
{
    int i, n = [input length];
    char *buffer = malloc((n+1)*sizeof(char));
    for (i=0;i<n;i++)
        buffer[i]=[input characterAtIndex:i]-1;
    buffer[i] = 0;
    NSString *output = [NSString stringWithCString:buffer];
    free(buffer);
    return output;
}

- (BOOL) tableView: (NSTableView *) tableView shouldEditTableColumn: (NSTableColumn *) tableColumn row: (int) rowIndex
{
    if ([movie isOffline]) return NO;
    NSArray *bad = [NSArray arrayWithObjects:@"Type", @"Enabled", @"Size", @"Preload", @"High Quality", nil];
    NSString *idString = [tableColumn identifier];
    int i, n = [bad count];
    for (i=0;i<n;i++)
        if ([idString isEqualToString:[bad objectAtIndex:i]])
            return NO;
    if ([idString isEqualToString:@"Format"] && ![[NSUserDefaults standardUserDefaults] boolForKey:[self reduce:@"tvqfsFeju"]])
        return NO;
    return YES;
}

- (void)doubleClick
{
    if ([movie isOffline]) return;
    int clickedColumn = [tracksTable clickedColumn];
	NSString *idString = nil;
	int row = [tracksTable clickedRow];
	NSTableColumn *tcol = [[tracksTable tableColumns] objectAtIndex:clickedColumn];
	if (-1 != clickedColumn) idString = [tcol identifier];
	if (-1 != row) {
        if ([idString isEqualToString:@"Enabled"]) {
            BOOL enabled = [[(MHMovie *)movie trackAtIndex:row] enabled];
            [[(MHMovie *)movie trackAtIndex:row] setEnabled:!enabled];
        } else if ([idString isEqualToString:@"Preload"]) {
            MHTrack *track = [(MHMovie *)movie trackAtIndex:row];
            [track setPreloads:![track preloads]];
        } else if ([idString isEqualToString:@"High Quality"]) {
            MHTrack *track = [(MHMovie *)movie trackAtIndex:row];
            [track setHighQuality:![track highQuality]];
        } else {
			if ([self tableView:tracksTable shouldEditTableColumn:tcol row:row]) {
				[tracksTable editColumn:clickedColumn row:row withEvent:[NSApp currentEvent] select:YES];
			}
			return;
		}
        [tracksTable reloadData];
    }
}

- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
{
    switch ([tracksTable numberOfSelectedRows]) {
        case 0: [deleteButton setEnabled:NO]; break;
        case 1: [deleteButton setEnabled:YES];
                [deleteButton setTitle:@"Delete Track"]; break;
        default: [deleteButton setEnabled:YES];
                [deleteButton setTitle:@"Delete Tracks"]; break;
    }
}

- (NSDragOperation)tableView:(NSTableView*)tableView validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)operation
{
    //if (!row || row == [playlistTable selectedRow]) return NSDragOperationNone;
    //NSLog(@"copy");
    if ([movie isOffline]) return NSDragOperationNone;
    return NSDragOperationCopy;
}

- (BOOL)tableView:(NSTableView*)tableView acceptDrop:(id <NSDraggingInfo>)info row:(int)row dropOperation:(NSTableViewDropOperation)operation
{
    if ([movie isOffline]) return NO;
    NSPasteboard *pboard = [info draggingPasteboard];
    if (![[pboard types] containsObject:NSFilenamesPboardType] ) return NO;
    NSArray *files = [pboard propertyListForType:NSFilenamesPboardType];
    int i, n = [files count];
    BOOL changed = NO;
    for (i=0;i<n;i++) {
        MHMovie *newMovie = [[MHMovie alloc] initWithPath:[files objectAtIndex:i]];
        if (newMovie) {
            if ([newMovie trackCount] == 1 && ![[newMovie trackAtIndex:0] name])
                [[newMovie trackAtIndex:0] setName:[[[files objectAtIndex:i] lastPathComponent] extensionRemoved]];
            int oldTrackCount = [movie trackCount];
            SetMovieSelection([newMovie QTMovie], 0, GetMovieDuration([newMovie QTMovie]));
            AddMovieSelection([movie QTMovie], [newMovie QTMovie]);
            [newMovie release];
            newMovie = nil;
            int j, newTrackCount = [movie trackCount];
            for (j=oldTrackCount; j<newTrackCount; j++) {
                [[movie trackAtIndex:j] setOffset:0];
            }
            [tracksTable reloadData];
            changed = YES;
        }
    }
    if (changed) [movie gatherData];
    return YES;
}


@end
