/*
 * Session.java
 *
 * Copyright (c) 2007  Vreixo Formoso
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * See COPYING file for details.
 */

package org.pykix.libburnia.libburn;

import org.pykix.libburnia.bindings.Proxy;

/**
 * References a single session on a disc.
 * 
 * @author Vreixo Formoso
 * @since 0.1
 */
public class Session extends Proxy {
	
	public static final int POS_END = 100;

	/** wether is needed to free or not the session when no more needed */
	private boolean free;
	
	/**
	 * Create a new session.
	 */
	public Session() {
		super( burn_session_create() );
		free = true;
	}
	
	/* package protected */
	Session(long ptr) {
		super(ptr);
		free = false;
	}
	
	/**
	 * Add a track to session at specified position.
	 * 
	 * @param track
	 * 		Track to insert in session.
	 * @param pos
	 * 		position to add at ({@link #POS_END} is "at the end")
	 * @return
	 * 		<code>true</code> if success, <code>false</code> if track can't 
	 * 		be added.
	 */
	public boolean addTrack(Track track, int pos) {
		
		if ( pos > POS_END ) {
			return false;
		}
		
		return burn_session_add_track( pointerOf(this), pointerOf(track), pos);
	}
	
	/**
	 * Remove a track from this session.
	 * 
	 * @param track
	 * 		Track to find and remove.
	 * @return
	 * 		<code>true</code> if success, <code>false</code> for failure,
	 * 		for example if track was not previously added to this session.
	 */
	public boolean removeTrack(Track track) {
		return burn_session_remove_track( pointerOf(this), pointerOf(track) ); 
	}
	
	/**
	 * Hide the first track in the "pre gap" of the disc.
	 * 
	 * @param onoff
	 * 		<code>true</code> to enable hiding, <code>false</code> to disable.
	 */
	public void hideFirstTrack(boolean onoff) {
		burn_session_hide_first_track( pointerOf(this), onoff ? 1 : 0 );
	}
	
	/**
	 * Tells how long the session will be on disc.
	 * 
	 * @return
	 * 		Number of sectors the session will need.
	 */
	public int getSectors() {
		return burn_session_get_sectors( pointerOf(this) );
	}
	
	/**
	 * Gets a copy of the {@link TocEntry} structure associated with the
	 * session's lead out.
	 * 
	 * @return
	 * 		A {@link TocEntry} object.
	 */
	public TocEntry getLeadoutEntry() {
		return burn_session_get_leadout_entry( pointerOf(this) );
	}
	
	/**
	 * Gets an array of all the tracks for a session.
	 * 
	 * <p>
	 * <b>THIS IS NO LONGER VALID AFTER YOU ADD OR REMOVE A TRACK</b>
	 * 
	 * FIXME when a track is removed, its C struct can be deleted, thus
	 * the java object is no longer valid. If we still have a reference
	 * for the track originally created, the C struct is not deleted because
	 * we have a reference to it. For now, this behavior is not so bad... 
	 * 
	 * @return
	 * 		An array with all the tracks.
	 */
	public Track[] getTracks() {
		
		long[] tracksPtrs = burn_session_get_tracks( pointerOf(this) );
		
		Track[] tracks = new Track[tracksPtrs.length];
		
		for ( int i = 0; i < tracksPtrs.length; ++i ) {
			
			long ptr = tracksPtrs[i];
			
			Track track = (Track) proxyFor(ptr);
			if (track == null) {
				track = new Track(ptr);
			}
			tracks[i] = track;
		}
		
		return tracks;
	}
	
	/**
	 * Returns whether the first track of a session is hidden in the pregap.
	 * 
	 * @return
	 * 		<code>true</code> if the first track is hidden, <code>false</code>
	 * 		otherwise
	 */
	public boolean isHideFirstTrack() {
		return burn_session_get_hidefirst( pointerOf(this) );
	}
	
	@Override
	protected void finalize() throws Throwable {
		super.finalize();
		
		if ( free ) {
			burn_session_free( pointerOf(this) );
		}
	}
	
	private static native long burn_session_create();

	private static native void burn_session_free(long s);
	
	private static native boolean burn_session_add_track(long s, long t, 
			int pos);
	
	private static native boolean burn_session_remove_track(long s, long t);
	
	private static native void burn_session_hide_first_track(long s, 
			int onoff);
	
	private static native int burn_session_get_sectors(long s);
	
	private static native TocEntry burn_session_get_leadout_entry(long s);
	
	private static native long[] burn_session_get_tracks(long s);
	
	private static native boolean burn_session_get_hidefirst(long session);
	
}
