/**
 *#########################################################################
 *
 * A component of the Gatherer application, part of the Greenstone digital
 * library suite from the New Zealand Digital Library Project at the
 * University of Waikato, New Zealand.
 *
 * Author: John Thompson, Greenstone Digital Library, University of Waikato
 *
 * Copyright (C) 1999 New Zealand Digital Library Project
 *
 * This program 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.
 *
 * 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, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *########################################################################
 */
package org.greenstone.gatherer.download;

import java.io.*;
import java.util.*;
import org.greenstone.gatherer.util.StaticStrings;
import org.greenstone.gatherer.util.Utility;
import org.w3c.dom.*;
import org.greenstone.gatherer.cdm.*;


/** This class is responsible for storing information from a parsed downloadinfo.pl call in such a way that it allows easy access to parsed details for the purposes of user design and specification of downloads.
 * @author John Thompson, Greenstone Digital Library, University of Waikato
 * @version 2.3
 */
public class Download
    extends ArgumentContainer
{
    private boolean is_abstract = false;

    /** A reference to the download that this one inherits from. */
    private Download super_download = null;
    /** The element this download is based upon. */
    private Element element;
    /** A description of this download. */
    private String description = null;
    private String name = null;


    public Download() {
    }

    /** Method to add an argument to this download. Only adds the argument if it isn't already present.
     * @param argument The <strong>Argument</strong> to add.
     */
    public void addArgument(Argument argument) {
	if(element == null && !contains(argument)) {
	    add(argument);
	    argument.setOwner(name);
	}
    }

    /** Method to compare two downloads for ordering.
     * @param object The download we are comparing to, as an <strong>Object</strong>.
     * @return An <i>int</i> specifying the download order, using values as set out in String.
     * @see java.lang.String#compareTo
     */
    public int compareTo(Object object) {
	if(object == null) {
	    return -1;
	}
	return toString().compareTo(object.toString());
    }

    /** Probably not used.
     */
    public DOMProxyListEntry create(Element element) {
	return null;
    }

    /** Method to determine if two downloads are equal.
     * @param object The download to test against, as an <strong>Object</strong>.
     * @return <i>true</i> if the download names match, <i>false</i> otherwise.
     */
    public boolean equals(Object object) {
	return (compareTo(object) == 0);
    }

    /** Method to retrieve an argument by its name.
     * @param name The name of the argument as a <strong>String</strong>.
     * @return The <strong>Argument</strong> requested, or <i>null</i> if no such argument.
     */
    public Argument getArgument(String name) {
	// The name given may still include the '-'
	if(name.startsWith("-")) {
	    name = name.substring(1);
	}
	ArrayList arguments = getArguments(true, true);
	for(int i = 0; i < arguments.size(); i++) {
	    Argument argument = (Argument)arguments.get(i);
	    if(argument.getName().equals(name)) {
		return argument;
	    }
	}
	return null;
    }

     /** Retrieve all of the arguments available to this base download, including its super downloads arguments. Some complexity is added by allowing the caller to choose whether they want normal arguments, custom arguments, or both.
      * @return an ArrayList of all of the arguments, starting with those for this download and ending with the arguments for basplug or similiar root download
      */
    public ArrayList getArguments(boolean include_normal, boolean include_custom) {
	ArrayList arguments = new ArrayList();
	if(include_normal && include_custom) {
	    arguments.addAll(this);
	}
	else {
	    int size = size();
	    for(int i = 0; i < size; i++) {
		Argument argument = (Argument) get(i);
		if(argument.isCustomArgument()) {
		    if(include_custom && !arguments.contains(argument)) {
			arguments.add(argument);
		    }
		}
		else {
		    if(include_normal && !arguments.contains(argument)) {
			arguments.add(argument);
		    }
		}
		argument = null;
	    }
	}
	if(super_download != null) {
	    ArrayList remainder = super_download.getArguments(include_normal, include_custom);
	    remainder.removeAll(arguments);
	    arguments.addAll(remainder);
	}
	return arguments;
    }

    public String getDescription() {
	return description;
    }

    public Element getElement() {
	return element;
    }

    /** Method to retrieve a download name.
     * @return A <strong>String</strong> containing the downloads name.
     */
    public String getName() {
	if(name == null && element != null) {
	    name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
	}
	return name;
    }

    public boolean isAbstract() {
	return is_abstract;
    }

    public boolean isAssigned() {	
	return (element != null && !element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR));
    }

    public void setAssigned(boolean assigned) {
	if(element != null) {
	    element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
	}
    }


    /** Method to set the value of desc.
     * @param description The new value of desc as a <strong>String</strong>.
     */
    public void setDescription(String description) {
	this.description = description;
    }

    public void setElement(Element element) {
	this.element = element;
    }

    public void setIsAbstract(boolean is_abstract) {
	this.is_abstract = is_abstract;
    }

    /** Method to set the value of name.
     * @param name The new value of name as a <strong>String</strong>.
     */
    public void setName(String name) {
	this.name = name;
    }

    /** Method to set the value of the super_download.
     * @param super_download The new value of super_download as a <strong>Download</strong>, or <i>null</i> if this class has no inheritance.
     */
    public void setSuper(Download super_download) {
	this.super_download = super_download;
    }
}
