/**
 * Copyright (C) 2010 Orbeon, Inc.
 *
 * 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
 * 2.1 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 Lesser General Public License for more details.
 *
 * The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
 */
package org.orbeon.oxf.xforms.processor.handlers.xml;

import org.orbeon.oxf.common.OrbeonLocationException;
import org.orbeon.oxf.xforms.XFormsConstants;
import org.orbeon.oxf.xforms.control.XFormsControl;
import org.orbeon.oxf.xforms.control.controls.XFormsRepeatControl;
import org.orbeon.oxf.xml.XMLReceiverHelper;
import org.orbeon.oxf.xml.dom4j.ExtendedLocationData;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;

/**
 * Handle xf:repeat.
 */
public class XFormsRepeatHandler extends XFormsControlLifecyleHandlerXML {
	
	public XFormsRepeatHandler() {
		super(true, true);
	}
	
	@Override
    protected void handleControlStart(String uri, String localname, String qName, Attributes attributes,
                                      final String effectiveId, XFormsControl control) throws SAXException {
		
		super.handleControlStart(uri, localname, qName, attributes, effectiveId, control);
		
		final ContentHandler contentHandler = handlerContext.getController().getOutput();
		
		final boolean isTopLevelRepeat = handlerContext.countParentRepeats() == 0;
        final boolean isRepeatSelected = handlerContext.isRepeatSelected() || isTopLevelRepeat;
        
        final int currentIteration = handlerContext.getCurrentIteration();

        final XFormsRepeatControl repeatControl = handlerContext.isTemplate() ? null : (XFormsRepeatControl) containingDocument.getControlByEffectiveId(effectiveId);
        final boolean isConcreteControl = repeatControl != null;
        
        if (isConcreteControl) {
        	final int currentRepeatIndex = (currentIteration == 0 && !isTopLevelRepeat) ? 0 : repeatControl.getIndex();
            final int currentRepeatIterations = (currentIteration == 0 && !isTopLevelRepeat) ? 0 : repeatControl.getSize();
            
            // Unroll repeat
            for (int i = 1; i <= currentRepeatIterations; i++) {
            	// Is the current iteration selected?
                final boolean isCurrentIterationSelected = isRepeatSelected && i == currentRepeatIndex;
                
                reusableAttributes.clear();
                reusableAttributes.addAttribute(XFormsConstants.XXFORMS_NAMESPACE_URI, "selected", XFormsConstants.XXFORMS_PREFIX + ":selected", XMLReceiverHelper.CDATA, isCurrentIterationSelected?"true":"false");
            	contentHandler.startElement(XFormsConstants.XXFORMS_NAMESPACE_URI, "iteration", XFormsConstants.XXFORMS_PREFIX + ":iteration", reusableAttributes);
                
                // Apply the content of the body for this iteration
                handlerContext.pushRepeatContext(false, i, isCurrentIterationSelected);
                try {
                    handlerContext.getController().repeatBody();
                } catch (Exception e) {
                    throw OrbeonLocationException.wrapException(e, new ExtendedLocationData(repeatControl.getLocationData(), "unrolling xf:repeat control", repeatControl.element()));
                }
                handlerContext.popRepeatContext();
                
                contentHandler.endElement(XFormsConstants.XXFORMS_NAMESPACE_URI, "iteration", XFormsConstants.XXFORMS_PREFIX + ":iteration");
            }
        }
        	
	}
}
