package metab;
import metab.*;
import java.io.*;


/**
 * The <code>Intestine</code> class simulates the Small Intestine compartment
 * in the Compartmental model.  The only actual job that the small intestine
 * accomplishes in relation to the metabolism of ethanol is transport the ethanol
 * from the small intestine to the blood via the villi contained in the intestinal
 * wall.  No ethanol is actually metabolized in the small intestine, but it is
 * instead a factor that just delays transport to the <code>LeanBodyMass</code>.
 * The user must handle the transport of the ethanol and liquid between other
 * compartments by using the addLiquid and addContents methods for each compartment.
 * To implement, all that is required is the amount of ethanol (g), and the total
 * liquid volume (L).  An optional extra description (label) may be included, but
 * is not required for the class to function properly.
 * @author Levi Blackstone, Matthew Woller
 * @version 1.19
 * @see metab.Stomach
 * @see metab.LeanBodyMass
 * @see metab.NMSubject
 */
public class Intestine implements Serializable{

    /**
     * Ethanol transport rate constant from intestine to lean body mass (L/min).
     */
    private static final double ki = 0.107;//.107
    /**
     * Amount of ethanol (g).
     */
    private double amount;
    /**
     * Amount of total liquid in the small intestine (L).
     */
    private double liquid;
	/**
	 * Optional label for Compartment.
	 */
    private String label;

	/**
	 * Constructor for intestine compartment.
	 * @param amount Amount of ethanol (g).
	 * @param liquid Amount of liquid including beverages and gastric fluid (L).
	 * @see metab.Intestine#Intestine(double , double , String)
	 */
    Intestine(double amount, double liquid) {

        this.amount = amount;
        this.liquid = liquid;

    }

	/**
	 * Constructor for intestine compartment.
	 * @param amount Amount of ethanol (g).
	 * @param liquid Amount of liquid including beverages and gastric fluid (L).
	 * @param label Optional description for compartment.
	 * @see metab.Intestine#Intestine(double , double)
	 */
    Intestine(double amount, double liquid, String label) {

        this.amount = amount;
        this.liquid = liquid;
		this.label = label;

    }

	/**
	 * Adds ethanol to the intestine compartment (can be a negative value).
	 * @param newContents Amount of ethanol being transfered (g).
	 */
    public void addContents(double newContents) {

        if (amount + newContents < 0.00) {
        	amount = 0.00;
        } else {
			amount += newContents;
		}

    }

	/**
	 * Adds liquid from the beverage(s) and gastric fluid.
	 * @param newLiquid Amount of liquid being transfered (L).
	 */
    public void addLiquid(double newLiquid) {

    	if (this.liquid + newLiquid < 0.00) {
    		this.liquid = 0.00;
    	} else {
			this.liquid += newLiquid; // L
		}

    }

	/**
	 * Resets compartment.
	 */
    public void clear() {

        amount = 0.0;
        liquid = 0.0;

    }

	/**
	 * Retrieves amount of ethanol remaining in intestine.
	 * @return <Code>double</Code> representing amount of ethanol (g).
	 */
    public double getContents() {

        return amount;

    }

	/**
	 * Retrieves the optional label.
	 * @return <Code>String</Code> representing label.
	 */
    public String getLabel() {

        return label;

    }

	/**
	 * Retrieves amount of liquid remaining in intestine.
	 * @return <Code>double</Code> representing amount of liquid (L).
	 */
    public double getLiquid() {

    	return liquid;

    }

	/**
	 * Checks to see if any ethanol remains in intestine.
	 * @return <Code>boolean</Code> specifying if intestine is empty.
	 */
    public boolean isEmpty() {

        return (amount <= 0.0);

    }

	/**
	 * Computes amount of ethanol being absorbed into lean body mass.
	 * @return <Code>double</Code> representing rate of absorption (g/min).
	 */
    public double computeEthanolAbsorption() {

        if (liquid <= 0.0){
            return amount;
        } else {
            double concentration = amount/liquid; //g/L
            return (ki * concentration); // g/min
        }

	}

	/**
	 * Sets optional label.
	 * @param newLabel String representing new label.
	 */
    public void setLabel(String newLabel) {

        label = newLabel;

    }

}