package org.baderlab.lola;

import org.baderlab.lola.resources.LolaResources;
import org.baderlab.brain.Brain;
import org.baderlab.brain.AminoAcidGrouping;

import java.io.File;

/**
 Copyright 2007 Bader Lab

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
 the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

 */

/**
 * Container for all user-provided parameters.
 *
 * User: moyez
 * Date: May 27, 2007
 * Time: 5:04:24 PM
 */
public class LolaParameterSet {

    //parameters
    private File profileFile = null;    //file containing profile or project file pointing to a set of profiles
    private File codonBiasFile = null;  //file containing a codon bias specification
    private boolean uniquePeptides;     //if true, load only unique peptides from profile; else load all peptides
    private double fuzzFactor;          //protein profile fuzz factor used as distance matrix pseudocount value
    private File outputPath = null;     //output directory path in which to save results
    private int logoStartIndex;         //the starting number on the logo graph X-axis
    private int logoHeight;             //the height, in pixels, of the logo
    private double logoTrimPercentage;  //height threshold (in % of max height) of colums on either side of profile
    private String logoImageFormat;     //format of the logo image file
    private String treeTitle;           //title for logo tree
    private String treeImageFormat;     //output format of logo tree
    private String treeFilename;        //output file name for logo tree
    private double treeLeafTrimFactor;  //logo tree leaf node trim factor
    private double treeInternalNodeTrimFactor;  //logo tree internal node trim factor
    private String treeLeafOrderingMethod; //logo tree leaf ordering method
    private AminoAcidGrouping aaGrouping;  //parameters for amino acid grouping and colouring

    /**
     * Create a new parameter set with no values provided
     */
    public LolaParameterSet() {
        profileFile = null;
        codonBiasFile = null;
        uniquePeptides = LolaResources.UNIQUE_PEPTIDES_DEFAULT;
        fuzzFactor = LolaResources.FUZZ_FACTOR_DEFAULT;
        outputPath = null;
        logoStartIndex = LolaResources.LOGO_START_INDEX_DEFAULT;
        logoHeight = LolaResources.LOGO_HEIGHT_DEFAULT;
        logoTrimPercentage = LolaResources.LOGO_TRIM_PERCENTAGE_DEFAULT;
        logoImageFormat = LolaResources.LOGO_IMAGE_FORMAT_DEFAULT;
        treeTitle = LolaResources.TREE_TITLE;
        treeImageFormat = LolaResources.TREE_IMAGE_FORMAT_DEFAULT;
        treeFilename = null;
        treeLeafTrimFactor = Brain.LEAFNODE_TRIM_FACTOR_DEFAULT;
        treeInternalNodeTrimFactor = Brain.INTERNALNODE_TRIM_FACTOR_DEFAULT;
        treeLeafOrderingMethod = Brain.LEAF_ORDERING_DEFAULT;
        aaGrouping = new AminoAcidGrouping();
    }

    /**
     * Create a new parameter set with ALL PARAMETER VALUES provided
     * @param profileFile
     */
    public LolaParameterSet(
            File profileFile,
            File biasFile,
            boolean uniquePeptides,
            double fuzzFactor,
            File outputPath,
            int logoStartIndex,
            int logoHeight,
            double logoTrimPercentage,
            String logoImageFormat,
            String treeTitle,
            String treeImageFormat,
            String treeFilename,
            double treeLeafTrimFactor,
            double treeInternalNodeTrimFactor,
            String treeLeafOrderingMethod,
            AminoAcidGrouping aaGrouping
    ) {
        this.profileFile = profileFile;
        this.codonBiasFile = biasFile;
        this.uniquePeptides = uniquePeptides;
        this.fuzzFactor = fuzzFactor;
        this.outputPath = outputPath;
        this.logoStartIndex = logoStartIndex;
        this.logoHeight = logoHeight;
        this.logoTrimPercentage = logoTrimPercentage;
        this.logoImageFormat = logoImageFormat;
        this.treeTitle = treeTitle;
        this.treeImageFormat = treeImageFormat;
        this.treeFilename = treeFilename;
        this.treeLeafTrimFactor = treeLeafTrimFactor;
        this.treeInternalNodeTrimFactor = treeInternalNodeTrimFactor;
        this.treeLeafOrderingMethod = treeLeafOrderingMethod;
        this.aaGrouping = aaGrouping;
    }

    /**
     * Create a new parameter set with ONLY SEQUENCE LOGO PARAMETERS provided
     * @param profileFile
     */
    public LolaParameterSet(
            File profileFile,
            File biasFile,
            boolean uniquePeptides,
            double fuzzFactor,
            File outputPath,
            int logoStartIndex,
            int logoHeight,
            double logoTrimPercentage,
            String logoImageFormat,
            String logoColorStyle,
            AminoAcidGrouping aaGrouping

    ) {
        this.profileFile = profileFile;
        this.codonBiasFile = biasFile;
        this.uniquePeptides = uniquePeptides;
        this.fuzzFactor = fuzzFactor;
        this.outputPath = outputPath;
        this.logoStartIndex = logoStartIndex;
        this.logoHeight = logoHeight;
        this.logoTrimPercentage = logoTrimPercentage;
        this.logoImageFormat = logoImageFormat;
        this.aaGrouping = aaGrouping;
    }

    /**
     * Copies a parameter set object
     * @return A copy of the parameter set
     */
    public LolaParameterSet copy() {
        LolaParameterSet newParamSet = new LolaParameterSet(
                this.getProfileFile(),
                this.getCodonBiasFile(),
                this.getUniquePeptides(),
                this.getFuzzFactor(),
                this.getOutputPath(),
                this.getLogoStartIndex(),
                this.getLogoHeight(),
                this.getLogoTrimPercentage(),
                this.getLogoImageFileFormat(),
                this.getTreeTitle(),
                this.getTreeImageFormat(),
                this.getTreeFilename(),
                this.getTreeLeafTrimFactor(),
                this.getTreeInternalNodeTrimFactor(),
                this.getTreeLeafOrderingMethod(),
                this.getAminoAcidGrouping()
        );
        
        return newParamSet;
    }

    /* Paramter setters and getters */

    /**
     * @return The File object for the Profile file
     */
    public File getProfileFile() {
        return profileFile;
    }

    /**
     * Sets the Profile file name. This can be a single peptide file or a project file
     * that links to one ore more peptide files.
     *  
     * @param file A File object for the Profile file to be processed
     */
    public void setProfileFile(File file) {
        this.profileFile = file;
    }

    /**
     * Returns the user-provided codon bias specification file.
     * @return A File object for the codon bias file.
     */
    public File getCodonBiasFile() {
        return codonBiasFile;
    }

    /**
     * Sets the user-provided codon bias specification file.
     * @param file A File object for the codon bias file.
     */
    public void setCodonBiasFile(File file) {
        this.codonBiasFile = file;
    }

    /**
     * Gets the user-selected value of the unique peptides flag; true iff only unique peptides should be loaded
     * from the profile.
     * @return True iff only unique peptides should be loaded from the profile; false otherwise.
     */
    public boolean getUniquePeptides() {
        return uniquePeptides;
    }

    /**
     * Sets the flag that determines whether only unique peptides should be loaded from the profile.
     * @param value The value of the flag.
     */
    public void setUniquePeptides(boolean value) {
        this.uniquePeptides = value;
    }

    /**
     * Gets the user-selected fuzz factor value for protein profiles.
     * @return fuzz factor value
     */
    public double getFuzzFactor() {
        return fuzzFactor;
    }

    /**
     * Sets the protein profile fuzz factor.
     * @param value fuzz factor
     */
    public void setFuzzFactor(double value) {
        this.fuzzFactor = value;
    }

    /**
     * Returns the output directory path in which to save results.
     * @return File object holding the output path
     */
    public File getOutputPath() {
        return outputPath;
    }

    /**
     * Sets the output directory path in which to save results.
     * @param path File object holding the output path
     */
    public void setOutputPath(File path) {
        this.outputPath = path;
    }

    /**
     * Returns the starting number on the logo graph X-axis.
     * @return Integer value for the logo start index
     */
    public int getLogoStartIndex() {
        return logoStartIndex;
    }

    /**
     * Sets the starting number on the logo graph X-axis.
     * @param index Integar value for the logo start index
     */
    public void setLogoStartIndex(int index) {
        this.logoStartIndex = index;
    }

    /**
     * Returns the height, in pixels, of the logo image.
     * @return Integer value for the logo height
     */
    public int getLogoHeight() {
        return logoHeight;
    }

    /**
     * Sets the height, in pixels, of the logo image.
     * @param height Integer value for the logo height
     */
    public void setLogoHeight(int height) {
        this.logoHeight = height;
    }

    /**
     * Returns the height threshold (in % of maximum column height) of columns on either side of profile.
     * Any columns exceeding this threshold are trimmed to the specified percentage.
     * The setting has the effect of highlighting the most informative contiguous region.
     * @return Double value for the logo trim percentage
     */
    public double getLogoTrimPercentage() {
        return logoTrimPercentage;
    }

    /**
     * Sets the height threshold (in % of maximum column height) of columns on either side of profile.
     * Any columns exceeding this threshold are trimmed to the specified percentage.
     * The setting has the effect of highlighting the most informative contiguous region.
     * @param percentage A <b>double</b> value, between 0 and 1, for the logo trim percentage.
     */
    public void setLogoTrimPercentage(double percentage) {
        this.logoTrimPercentage = percentage;
    }

    /**
     * Returns the logo image file format as an ImageFormat enumeration value.
     * @return A String value representing the image format
     */
    public String getLogoImageFileFormat() {
        return logoImageFormat;
    }

    /**
     * Sets the logo image file format as an ImageFormat enumeration value.
     * @param imageFormat An ImageFormat value
     */
    public void setLogoImageFormat(String imageFormat) {
        this.logoImageFormat = imageFormat;
    }

    /**
     * Returns the title of the logo tree.
     * @return String
     */
    public String getTreeTitle() {
        return this.treeTitle;
    }

    /**
     * Sets the title of the logo tree.
     * @param treeTitle String
     */
    public void setTreeTitle(String treeTitle) {
        this.treeTitle = treeTitle;
    }

    /**
     * Returns the image format of the logo tree as an ImageFormat enumeration value.
     * @return ImageFormat
     */
    public String getTreeImageFormat() {
        return this.treeImageFormat;
    }

    /**
     * Sets the image format of the logo tree.
     * @param treeImageFormat An ImageFormat enumeration value.
     */
    public void setTreeImageFormat(String treeImageFormat) {
        this.treeImageFormat = treeImageFormat;
    }

    /**
     * Returns the filename of the logo tree. Only returns the name of the file, without the filesystem path.
     * @return String
     */
    public String getTreeFilename() {
        return this.treeFilename;
    }

    /**
     * Sets the filename of the logo tree. THIS VALUE SHOULD NOT INCLUDE THE RELATIVE/ABSOLUTE PATH,
     * ONLY THE NAME OF THE FILE is required.
     * @param treeFilename String
     */
    public void setTreeFilename(String treeFilename) {
        this.treeFilename = treeFilename;
    }

    /**
     * Returns the logo tree leaf node trimming factor.
     * @return String
     */
    public double getTreeLeafTrimFactor() {
        return this.treeLeafTrimFactor;
    }
    /**
     * Sets the logo tree leaf node trimming factor.
     * @param treeLeafTrimFactor double
     */
    public void setTreeLeafTrimFactor(double treeLeafTrimFactor) {
        this.treeLeafTrimFactor = treeLeafTrimFactor;
    }
    /**
     * Returns the logo tree leaf node trimming factor.
     * @return String
     */
    public double getTreeInternalNodeTrimFactor() {
        return this.treeInternalNodeTrimFactor;
    }
    /**
     * Sets the logo tree leaf node trimming factor.
     * @param treeInternalNodeTrimFactor double
     */
    public void setTreeInternalNodeTrimFactor(double treeInternalNodeTrimFactor) {
        this.treeInternalNodeTrimFactor = treeInternalNodeTrimFactor;
    }
    /**
     * Returns the amino acid grouping/coloring parameters
     * @return String
     */
    public AminoAcidGrouping getAminoAcidGrouping() {
        return this.aaGrouping;
    }
    /**
     * Sets the amino acid grouping/coloring parameters
     * @param aaGrouping double
     */
    public void setAminoAcidGrouping(AminoAcidGrouping aaGrouping) {
        this.aaGrouping = aaGrouping;
    }
    /**
     * Returns the leaf ordering method applied to the logo tree.
     * @return String
     */
    public String getTreeLeafOrderingMethod() {
        return this.treeLeafOrderingMethod;
    }

    /**
     * Sets the leaf ordering method applied to the logo tree.
     * @param treeLeafOrderingMethod String
     */
    public void setTreeLeafOrderingMethod(String treeLeafOrderingMethod) {
        this.treeLeafOrderingMethod = treeLeafOrderingMethod;
    }

    /**
     * Returns a string representation of the current parameter set.
     * 
     * @return A String that lists the names and values of the parameters.
     */
    public String toString() {
        StringBuffer sb = new StringBuffer();
        String lineSep = System.getProperty("line.separator");
        sb.append("Profile File: " + profileFile.toString() + lineSep);
        
        return sb.toString();
    }

}
