// Copyright (c) 2002, Peter Bentley
// 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.
// 
//   The name Peter Bentley may not 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.
//
// $Id: OmdToc.m,v 1.19 2003/08/22 18:17:49 pete Exp $

#import "OmdToc.h"
#import "OmdUnit.h"
#import "OmdTrackInfo.h"
#import "OmdGroupInfo.h"

CVSID( "$Id: OmdToc.m,v 1.19 2003/08/22 18:17:49 pete Exp $" );

@implementation OmdToc

- (id) initWithCToc: (omd_toc_t *) toc unit: (OmdUnit *) u
{
    if( (self = [super init]) != nil )
    {
        ctoc = toc;
	omdUnit = u;
    }
    return self;
}

- (void) dealloc
{
    if( ctoc )
    {
        omd_toc_free( ctoc );
    }
}


- (int) numTracks
{
    return ctoc ? ctoc->track_count : 0;
}

- (NSString *) title
{
    NSString *str = nil; // = @"Untitled";
    
    if( ctoc && ctoc->title )
    {
        str = [[[NSString alloc] initWithCString: ctoc->title] autorelease];
    }
    return str;
}


- (OmdTrackInfo *) trackInfo: (int) t
{
    OmdTrackInfo *info = nil;

    if( ctoc && (t >= 0) && (t < ctoc->track_count) )
    {
	info = [OmdTrackInfo alloc];
	[info initWithId: t andToc: self];
	[info autorelease];
    }
    return info;
}


- (int) numGroups
{
    return ctoc ? ctoc->group_count : 0;
}

- (OmdGroupInfo *) groupInfo: (int) g
{
    OmdGroupInfo *info = nil;
    
    if( ctoc && (g >= 0) && (g < ctoc->group_count) )
    {
	info = [OmdGroupInfo alloc];
	[info initWithId: g andToc: self];
	[info autorelease];
    }
    return info;
}



- (void) invalidate: (int) t
{
    omd_toc_invalidate_track( [omdUnit unit], ctoc, t );
}



- (int) setTitle: (NSString *) title forTrack: (int) num
{
    OmdTrackInfo *info = [self trackInfo: num];

    if( info && ! [title isEqualToString: [info titleString]] )
    {
        slog( LOG_INFO, "Set track %d, title to %s", num, [title lossyCString] );
        if( [omdUnit setTrack: num title: title] < 0 )
        {
            slog( LOG_INFO, "set track title failed!" );
            return -1;
        }
        else
        {
            [self invalidate: num];
        }
    }
    return 0;
}

- (int) setTitle: (NSString *) title forGroup: (int) num
{
    OmdGroupInfo *info = [self groupInfo: num];

    if( info && ! [title isEqualToString: [info titleString]] )
    {
        slog( LOG_INFO, "Set group %d, title to %s", num, [title lossyCString] );
        if( [omdUnit setGroup: num title: title] < 0 )
        {
            slog( LOG_INFO, "set group title failed!" );
            return -1;
        }
    }
    return 0;
}





- (int) setDiscTitle: (NSString *) title
{
    // set it in the C TOC
    if( omd_toc_set_title( ctoc, [title lossyCString] ) < 0 )
    {
        slog( LOG_ERROR, "Unable to set title\n" );
        return -1;
    }

    // Flush all group info out to disc
    if( omd_toc_write_title( [omdUnit unit], ctoc ) < 0 )
    {
        slog( LOG_ERROR, "TOC write failed" );
        return -1;
    }
    
    // Re-read from disk to be sure
    omd_toc_read_groups( [omdUnit unit], ctoc );
    return 0;
}

- (int) createGroup: (NSString *) name from: (int) start to: (int) finish;
{
    // Update the C TOC
    if( omd_toc_add_group( ctoc, start, finish, [name lossyCString] ) < 0 )
    {
        slog( LOG_ERROR, "Unable to create a new group\n" );
        return -1;
    }

    // Flush all group info out to disc
    if( omd_toc_write_title( [omdUnit unit], ctoc ) < 0 )
    {
        slog( LOG_ERROR, "TOC write failed" );
        return -1;
    }
    
    // Re-read from disk to be sure
    omd_toc_read_groups( [omdUnit unit], ctoc );
    return 0;
}

- (int) deleteGroup: (int) grpid
{
    // Update the C TOC
    if( omd_toc_delete_group( ctoc, grpid ) < 0 )
    {
        slog( LOG_ERROR, "Unable to delete group\n" );
        return -1;
    }

    // Flush all group info out to disc
    if( omd_toc_write_title( [omdUnit unit], ctoc ) < 0 )
    {
        slog( LOG_ERROR, "TOC write failed" );
        return -1;
    }
    
    // Re-read from disk to be sure
    omd_toc_read_groups( [omdUnit unit], ctoc );
    return 0;
}

- (int) deleteTrack: (int) trkid
{
    int rc = omd_toc_delete_track( [omdUnit unit], ctoc, trkid );
    
    if( rc < 0 )
    {
        slog( LOG_ERROR, "Track delete failed" );
        return -1;
    }

    slog( LOG_INFO, "%d groups changed", rc );
    if( rc == 0 )
    {
        return 0;
    }

    // Flush all group info out to disc
    if( omd_toc_write_title( [omdUnit unit], ctoc ) < 0 )
    {
        slog( LOG_ERROR, "TOC write failed" );
        return -1;
    }
    
    // Re-read from disk to be sure
    omd_toc_read_groups( [omdUnit unit], ctoc );
    return 0;
}

- (int) refresh
{
    return [omdUnit tocRefresh: self];
}

- (omd_toc_t *) ctoc
{
    return ctoc;
}

- (omd_track_t *) rawTrackInfo: (int) trk
{
    return [omdUnit rawTrackInfo: trk];
}

- (omd_group_t *) rawGroupInfo: (int) grp
{
    return [omdUnit rawGroupInfo: grp];
}

@end
