/**
 * Define an Integer object and do some iteration stuff
 *
 * Requires the following attributes:
 *  id - the ID
 *  scope - where in the PageContext space will it be
 *  life - what type of lifetime the definition will take
 * Optional attributes are:
 *  declare - whether the id is to be declared, or assumed to be so.
 *  startValue - value after doStartTag (invalid with life=="AT_END")
 *  endValue - value after doEndTag (invalid with life=="NESTED")
 *  initBodyValue - value after doInitTag (invalid with life=="AT_END")
 *  afterBodyIncrement - increment after doAfterTag (invalid with life=="AT_END")
 *  iterationCount - number of iterations to do (defaults to 1)
 */

package tags;

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.IOException;

public class Define extends BodyTagSupport {

    // the scope where to define the object
    public void setScope(String s) {
	if (s.equals("page")) {
	    scope = PageContext.PAGE_SCOPE;
	} else if (s.equals("session")) {
	    scope = PageContext.SESSION_SCOPE;
	} else if (s.equals("request")) {
	    scope = PageContext.REQUEST_SCOPE;
	} else if (s.equals("application")) {
	    scope = PageContext.APPLICATION_SCOPE;
	}
    }

    public String getScope() {
	switch (scope) {
	case PageContext.PAGE_SCOPE:
	    return "page";
	case PageContext.SESSION_SCOPE:
	    return "session";
	case PageContext.REQUEST_SCOPE:
	    return "request";
	case PageContext.APPLICATION_SCOPE:
	    return "application";
	default:
	    return null;
	}
    }

    // Lifetime 

    public void setLife(String s) {
	if (s.equals("nested")) {
	    life = VariableInfo.NESTED;
	} else if (s.equals("at_begin")) {
	    life = VariableInfo.AT_BEGIN;
	} else if (s.equals("at_end")) {
	    life = VariableInfo.AT_END;
	} else {
	    throw new Error("Oops! unexpected syntactic error");
	}
    } 

    public String getLife() {
	switch (life) {
	case VariableInfo.NESTED:
	    return "nested";
	case VariableInfo.AT_BEGIN:
	    return "at_begin";
	case VariableInfo.AT_END:
	    return "at_end";
	}
	return null;
    }

    // ====== Optional attributes =========


    // Whether to declare the scripting variable or not.

    public void setDeclare(String s) {
	declare = new Boolean(s);
    }


    // value after doStartTag (invalid with life=="AT_END")

    public void setStartValue(String v) {
	startValue = Integer.valueOf(v);
    }

    public String getStartValue() {
	return startValue.toString();
    }

    // value after doEndTag (invalid with life=="NESTED")

    public void setEndValue(String v) {
	endValue = Integer.valueOf(v);
    }

    public String getEndValue() {
	return endValue.toString();
    }

    // value after doInitBody (invalid with life=="AT_END")

    public void setInitBodyValue(String v) {
	initBodyValue = Integer.valueOf(v);
    }

    public String getInitBodyValue() {
	return initBodyValue.toString();
    }

    // increment after doAfterTag (invalid with life=="AT_END")

    public void setAfterBodyIncrement(String v) {
	afterBodyIncrement = Integer.parseInt(v);
    }

    // number of iterations to do (defaults to 1)

    public void setIterationCount(String v) {
	iterationCount = Integer.parseInt(v);
    }


    // ================== Actions ====================

    public int doStartTag() {
	if (startValue != null) {
	    pageContext.setAttribute(getId(), startValue, scope);
	}
	currentCount = 0;
System.err.println("finishing doStartTag()");
	return EVAL_BODY_TAG;
    }

    public void doInitBody() {
	if (initBodyValue != null) {
	    pageContext.setAttribute(getId(), initBodyValue, scope);
	}
	currentCount = 0;
System.err.println("finishing doInitBody()");
    }

    public int doAfterBody() throws JspException {
	BodyContent bd = getBodyContent();
	try {
	    bd.writeOut(getPreviousOut());
	    bd.clearBody();
	} catch (IOException ex) {
	    throw new JspTagException("io trouble in tag handler");
	}

	Integer value = (Integer) pageContext.getAttribute(getId());
        int k;
        if (value != null)
            k = value.intValue()+afterBodyIncrement;
        else
            k = afterBodyIncrement;

	pageContext.setAttribute(getId(), new Integer(k), scope);
	currentCount += 1;
	if (currentCount < iterationCount) {
System.err.println("finishing doAfterBody on EVAL_BODY_TAG");
	    return EVAL_BODY_TAG;
	} else {
System.err.println("finishing doAfterBody on SKIP_BODY");
	    return SKIP_BODY;
	}
    }

    public int doEndTag() {
	if (endValue != null) {
	    pageContext.setAttribute(getId(), endValue, scope);
	}
System.err.println("finishing doEndTag");
	return EVAL_PAGE;
    }

    // private data

    protected int scope = PageContext.PAGE_SCOPE;
    protected int life = VariableInfo.AT_BEGIN;
    protected Boolean declare;
    private Integer startValue;
    private Integer endValue;
    private Integer initBodyValue;
    private int afterBodyIncrement;
    protected int iterationCount = 1;
    protected int currentCount = 1;
}
