// generated by FBuilder
package flexa.ff;
import flexa.fb.*;
import java.util.Map;
import java.util.HashMap;
import javax.script.*;
import java.util.ArrayList;
public class subform extends FComponent {
    //
    // CONSTRUCTOR
    //
    public subform() {
        super("ff.subform");
    }
    
    // 
    // Methods
    //
    
    
    public void updateFromObject(FObjectInterface aObject, FContext aContext)  throws Exception { 
    		String tName = (String)this.getValue("name");
		Log.info("updateFromObject subform " + tName);
		if( tName != null && !tName.equals("") ) {
			if( aObject.hasMember(tName) ) {
			    FCollection fcol = (FCollection)aObject.getMember(tName);
			    this.fobject = fcol;
			    fcol.subform = this;
			    
			    //@todo this.removeClonedChildren();
			    int totalrows = fcol.size();
			    //this.removeClonedChildren(); 
		        // Agrega o actualiza filas
			    for(int i = 0; i < totalrows; i++) {
			        // Por cada objeto en la colección
			        FObject tobj = fcol.get(i);
			        // buscar obj en subformrows
			        subformrow srow = null;
			        for (FComponent element : this.getChildren()) {
			            if( element.getClass() == subformrow.class && ((subformrow)element).fobject == tobj ) {
		                    srow = (subformrow)element;
		                    break;
			            }
			        }
			        // Si no lo encuentra agrega subformrow con el objeto asociado
			        if( srow == null ) {
			            Log.info("Adding row to subform " +  tobj);
			            srow = this.cloneToRow();
			            srow.setValue("id", this.id + "[" + i + "]");
			            srow.setId(this.id + "[" + i + "]");
			            srow.setValue("rowvalid", this.getValue("rowvalid"));
			            srow.setValue("rowinvalidmessage", this.getValue("rowinvalidmessage"));
			            //this.addChild(srow);
			            srow.setFObject(tobj);
				    }
				    tobj.setForm(srow);
				    // Se actualiza desde el objeto a los hijos del subformrow
		            for (FComponent element : srow.getChildren()) {
				        element.updateFromObject(tobj, aContext); 
			        }	
			    }
			    // Elimina filas de más
			    ArrayList<FComponent> toberemoved = new ArrayList<FComponent>();
		        for (FComponent element : this.getChildren()) {
		            if( element.getClass() == subformrow.class ) {
		                FObject tobj = ((subformrow)element).fobject;
		                if( fcol.findObj(tobj) < 0 ) {
		                    Log.info("Removing row from subform " + tobj);
		                    //this.removeChild(element);
		                    toberemoved.add(element);
		                }
		            }
		        }
		        for (FComponent element : toberemoved) {
		            this.removeChild(element);
		        }
			} else {
			    Log.info("object " + aObject + " has not member " + tName);
			}
		}

    }
    


    
    public subformrow cloneToRow()  throws Exception { 
    		subformrow srow = new subformrow();
		// Gets bigger subformrows id
		int imax = -1;
		for( FComponent child: this.getChildren() ) {
		    if( !child.getType().equals("ff.subformrow") ) continue;
		    int ithis = child.getIndexFromId();
		    //Log.info(" child index "+  ithis);
		    if( ithis > imax ) imax = ithis;
		}
		// Calculates subformrow id
		String tnewid = this.id + "[" + (imax + 1) + "]";
		srow.setId(tnewid);
		srow.setName(tnewid);
		srow.setValue("rowvalid", this.getValue("rowvalid"));
		srow.setValue("rowinvalidmessage", this.getValue("rowinvalidmessage"));
		//srow.container = (String)this.getValue("name");
		// Rename children (fields): subformid[nn]_fieldname
		for (FComponent child : this.getChildren()) {
			//cloned.addChild((FComponent)child.clone());
			if( child.getType().equals("ff.subformrow") ) continue;
			FComponent tclonedchild = (FComponent)child.clone();
			tclonedchild.setId(tnewid + "_" + tclonedchild.getName());
		    srow.addChild(tclonedchild);
		}
		this.addChild(srow);
		return srow;

    }
    


    
    public subformrow add(FObject obj)  throws Exception { 
    		Log.info("add (from fobject)", obj);
		subformrow srow = this.cloneToRow(); // @todo falta pasarle el fobject para que se asocien cada atributo 
		srow.setFObject(obj);
		obj.form = srow;
		return srow;

    }
    


    
    public void clearrows()  throws Exception { 
    		ArrayList<FComponent> toremove = new ArrayList<FComponent>();
		for (FComponent child : this.getChildren()) {
		    if( child.getType().equals("ff.subformrow") ) {
		        toremove.add(child);
		    }
		}
		for( FComponent tremove : toremove ) {
			this.removeChild(tremove);
		}

    }
    


    
    public void setFObject(FObject aobject)  throws Exception { 
    		FCollection tcol = (FCollection)aobject.get(this.id);
		this.fobject = tcol;
		int tsize = tcol.size();
		int tii = -1;
		for (FComponent child : this.getChildren()) {
		    if( child.getType().equals("ff.subformrow") ) {
		        tii++;
		        child.setFObject(tcol.get(tii));
		    }
		}

    }
    


    
    public String validate(FContext aContext)  throws Exception { 
    		StringBuffer sb = new StringBuffer();
		boolean tisvalid = true;
		// Si el componentne tiene VALID evalua
		if( this.getValue("valid") != null ) {
			Object calcvalid = this.calcExpression(aContext, "valid");
			Log.info("Calcvalid " + this.getId(), calcvalid);
			if( !LibPrim.to_bool(calcvalid) ) {
				tisvalid = false;
				String tmessage = this.getValue("invalidmessage") != null ? (String)this.getValue("invalidmessage") : ("Valor invalido en " + this.getTitle());
				Log.info(tmessage);
				if( sb.length() > 0 ) sb.append("\n");
				sb.append(tmessage);
			}
		}
		// Solo valida subformrows
		int tii = 0;
		int tibak = this.fobject != null ? ((FCollection)this.fobject).getPosition() : 0;
		for (FComponent element : this.getChildren()) {
		    if( !element.getType().equals("ff.subformrow") ) continue;
		    if( this.fobject != null ) ((FCollection)this.fobject).setPosition(tii);
		    tii++;
			String tmessage2 = element.validate(aContext);
			if( !tmessage2.trim().equals("") ) {
				if( sb.length() > 0 ) sb.append("\n");
				sb.append(tmessage2);
			}
		}	
		if( this.fobject != null ) 
		    ((FCollection)this.fobject).setPosition(tibak);
		//((FCollection)this.fobject).setPosition(0);
		return sb.toString();

    }
    


    
    public boolean isvalid(FContext aContext)  throws Exception { 
    		boolean tisvalid = true;
		if( this.getValue("valid") != null ) {
			Object calcvalid = this.calcExpression(aContext, "valid");
			if( !LibPrim.to_bool(calcvalid) )
				tisvalid = false;
		}
		// Solo valida subformrows
		int tii = 0;
		int tibak = this.fobject != null ? ((FCollection)this.fobject).getPosition() : 0;
		for (FComponent element : this.getChildren()) {
		    if( !element.getType().equals("ff.subformrow") ) continue;
		    if( this.fobject != null ) ((FCollection)this.fobject).setPosition(tii);
		    tii++;
			if( !element.isValid(aContext) ) {
				tisvalid = false;
			}
		}		
		if( this.fobject != null ) 
		    ((FCollection)this.fobject).setPosition(tibak);
		return tisvalid;

    }
    


    
    public void removeChild(FComponent comp)  throws Exception { 
    		int tindex = this.getChildren().indexOf(comp);
		super.removeChild(comp);
		// Decrement index ID of descendants
		int tsize = this.getChildren().size();
		while(tindex < tsize) {
		    // Change index of descendants
		    ArrayList<FComponent> tdescendants = this.getChildren(tindex).getAllDescendants();
		    tdescendants.add(this.getChildren(tindex));
		    for(FComponent tdescendant: tdescendants) {
		        int tindex2 = tdescendant.getIndexFromId();
		        if( tindex2 >= 0 ) {
		            String tid = tdescendant.getId();
		            String tname = (String)tdescendant.getValue("name");
				    String tnewid = tid.substring(0, tid.indexOf("[") + 1) + (tindex2 - 1) + tid.substring(tid.indexOf("]"));
				    tdescendant.setId(tnewid);
				    if( tname.indexOf("[") > 0 ) {
				        String tnewname = tname.substring(0, tname.indexOf("[") + 1) + (tindex2 - 1) + tname.substring(tname.indexOf("]"));
				        tdescendant.setValue("name", tnewname);
				    }
				    
				    
		        }
		    }
		    tindex++;
		}

    }
    


    // 
    // Events
    //
	public void event(String aAction, FContext aContext) throws Exception {
        // Events
        
    
        // addevent EVENT
        if( LibText.stringToArray("" + this.id + ".add").contains(aAction) ) {
        			Log.info("SUBFORM event " + aAction + " my id " + this.id);
			// New subformrow
			subformrow srow = this.cloneToRow();
			// If it has FCollection asociated, add new Object to collection
			if( this.fobject != null ) {
			    Log.info("FCollection addNew");
			    FObject tobj = ((FCollection)this.fobject).addNewWithoutFormUpdate(aContext);
			    srow.setFObject(tobj);
			    tobj.form = srow;
			    srow.updateFromObject(tobj, aContext);
			}
			//this.addChild(srow);

        }
    


    
        // deleteevent EVENT
        if( LibText.stringToArray("" + this.id + ".delete").contains(aAction) ) {
        			// Remove myself
			if( this.fobject != null ) {
			    ((FCollection)this.fobject).remove(this.fobject); 
			}
			// Change index of all forward siblings 
			this.removeMyself();

        }
    


    
        // beforeopen EVENT
        if( LibText.stringToArray("beforeopen").contains(aAction) ) {
        			/**
			ArrayList<FComponent> notrendered = findChildsNotOfType("ff:subform","", "");
			for(FComponent child : notrendered) {
			    child.setValue("render", "no");
			}
			**/

        }
    


	    super.event(aAction, aContext);
	}
	
	
}