/*
 * MultiCaps.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;

/**
 * 
 * @author Vreixo Formoso
 * @since 0.1
 */
public class MultiCaps {

	private boolean multiSession;
	private boolean multiTrack;
	private boolean startAdr;
	private long startAlignment;
	private long startRangeLow;
	private long startRangeHigh;
	private int mightDoTao;
	private int mightDoSao;
	private int mightDoRaw;
	private WriteType advisedWriteMode;
	private WriteType selectedWriteMode;
	private Profile currentProfile;
	private boolean cdProfile;
	
	/* 
	 * this is not part of C burn_multi_caps struct, but is returned
	 * in burn_disc_get_multi_caps function
	 */
	private boolean writingPossible;
	
	/* be to called from JNI code */
	MultiCaps(boolean multiSession, boolean multiTrack, boolean startAdr, 
			long startAlignment, long startRangeLow, long startRangeHigh, 
			int mightDoTao, int mightDoSao, int mightDoRaw, 
			int advisedWriteMode, int selectedWriteMode, short currentProfile, 
			boolean cdProfile, boolean writingPossible) {
		
		super();
		this.multiSession = multiSession;
		this.multiTrack = multiTrack;
		this.startAdr = startAdr;
		this.startAlignment = startAlignment;
		this.startRangeLow = startRangeLow;
		this.startRangeHigh = startRangeHigh;
		this.mightDoTao = mightDoTao;
		this.mightDoSao = mightDoSao;
		this.mightDoRaw = mightDoRaw;
		this.advisedWriteMode = WriteType.values()[advisedWriteMode];
		this.selectedWriteMode = WriteType.values()[selectedWriteMode];
		this.currentProfile = Profile.get(currentProfile);
		this.cdProfile = cdProfile;
		this.writingPossible = writingPossible;
	}

	/**
	 * Get generally advised write mode.
	 * 
	 * <p>
	 * Not necessarily the one chosen by 
	 * {@link WriteOpts#setAutoWriteType(Disc, int)}
	 * because the {@link Disc} object might impose particular demands.
	 */
	public WriteType getAdvisedWriteMode() {
		return advisedWriteMode;
	}

	/**
	 * Wether the current profile indicates CD media. 
	 * 
	 * @return
	 * 		<code>true</code> = yes, <code>false</code> = no
	 */
	public boolean isCdProfile() {
		return cdProfile;
	}

	/**
	 * Profile which was current when the reply was generated.
	 */
	public Profile getCurrentProfile() {
		return currentProfile;
	}

	/**
	 * Potential availability of RAW write mode.
	 * 
	 * <p>
	 * With CD media (profiles 0x09 and 0x0a) check also the element
	 * {@link DriveInfo#getRawBlockTypes()}.
	 * 
	 * @return 
	 * <ul>
	 * 	<li>4= needs no size prediction, not to be chosen automatically
	 * 	<li>3= needs size prediction, not to be chosen automatically
	 * 	<li>2= available, no size prediction necessary
	 * 	<li>1= available, needs exact size prediction
	 * 	<li>0= not available
	 * </ul>
	 */
	public int getMightDoRaw() {
		return mightDoRaw;
	}

	/**
	 * Potential availability of SAO write mode.
	 * 
	 * <p>
	 * With CD media (profiles 0x09 and 0x0a) check also the element
	 * {@link DriveInfo#getSaoBlockTypes()}.
	 * 
	 * @return 
	 * <ul>
	 * 	<li>4= needs no size prediction, not to be chosen automatically
	 * 	<li>3= needs size prediction, not to be chosen automatically
	 * 	<li>2= available, no size prediction necessary
	 * 	<li>1= available, needs exact size prediction
	 * 	<li>0= not available
	 * </ul>
	 */
	public int getMightDoSao() {
		return mightDoSao;
	}

	/**
	 * Potential availability of TAO write mode.
	 * 
	 * <p>
	 * With CD media (profiles 0x09 and 0x0a) check also the element
	 * {@link DriveInfo#getTaoBlockTypes()}.
	 * 
	 * @return 
	 * <ul>
	 * 	<li>4= needs no size prediction, not to be chosen automatically
	 * 	<li>3= needs size prediction, not to be chosen automatically
	 * 	<li>2= available, no size prediction necessary
	 * 	<li>1= available, needs exact size prediction
	 * 	<li>0= not available
	 * </ul>
	 */
	public int getMightDoTao() {
		return mightDoTao;
	}

	/**
	 * Multi-session capability allows to keep the media appendable after
	 * writing a session. It also guarantees that the drive will be able
	 * to predict and use the appropriate Next Writeable Address to place
	 * the next session on the media without overwriting the existing ones.
	 * 
	 * <p>
	 * It does not guarantee that the selected write type is able to do
	 * an appending session after the next session. (E.g. CD SAO is capable
	 * of multi-session by keeping a disc appendable. But {@link #getMightDoSao()}
	 * will be 0 afterwards, when checking the appendable media.)
	 * 
	 * @return
	 * 		<code>true</code>= media may be kept appendable by 
	 * 		{@link WriteOpts#setMulti(boolean)} with <code>true</code> as
	 * 		parameter.
	 * 		<code>false</code>= media will not be appendable
	 */
	public boolean isMultiSession() {
		return multiSession;
	}

	/**
	 * Multi-track capability allows to write more than one track source
	 * during a single session. The written tracks can later be found in
	 * libburn's TOC model with their start addresses and sizes.
	 * 
	 * @return
	 * 		if <code>true</code>, multiple tracks per session are allowed,
	 * 		else, only one track per session allowed
	 */
	public boolean isMultiTrack() {
		return multiTrack;
	}

	/**
	 * Write mode as given by parameter wt of burn_disc_get_multi_caps().
	 */
	public WriteType getSelectedWriteMode() {
		return selectedWriteMode;
	}

	/**
	 * Start-address capability allows to set a non-zero address with
	 * {@link WriteOpts#setStartByte(long)}. Eventually this has to respect
	 * {@link #getStartAlignment()} and {@link #getStartRangeRow()},
	 * {@link #getStartRangeHigh()} in this structure.
	 * 
	 * @return
	 * 		if <code>true</code>, non-zero start address is allowed, otherwise
	 * 		only start address 0 is allowed (to depict the drive's own idea
	 * 		about the appropriate write start)
	 */
	public boolean isStartAdr() {
		return startAdr;
	}

	/**
	 * The alignment for start addresses. 
	 * ( start_address % start_alignment ) must be 0.
	 */
	public long getStartAlignment() {
		return startAlignment;
	}

	/**
	 * The highest addressable start address.
	 */
	public long getStartRangeHigh() {
		return startRangeHigh;
	}

	/**
	 * The lowest permissible start address.
	 */
	public long getStartRangeLow() {
		return startRangeLow;
	}
	
	/**
	 * @return
	 *		If <code>false</code>, writing seems impossible , else writing
	 *		is possible 
	 */
	public boolean isWritingPossible() {
		return writingPossible;
	}
	
}
