package org.opengroupware.jope.appserver.templates;

import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import org.opengroupware.jope.appserver.WOActionResults;
import org.opengroupware.jope.appserver.WOAssociation;
import org.opengroupware.jope.appserver.WOContext;
import org.opengroupware.jope.appserver.WOElement;
import org.opengroupware.jope.appserver.WORequest;
import org.opengroupware.jope.appserver.WOResponse;

/*
 * WOTemplate
 * 
 * This is just a simple element wrapper used for the root element of a 
 * template. It can transport additional information like the URL the
 * template is living at.
 */
public class WOTemplate extends WOElement {
  
  protected URL       url         = null;
  protected WOElement rootElement = null;
  protected Map<String, WOSubcomponentInfo> subcomponentInfos = null;
  
  public WOTemplate(URL _url, WOElement _root) {
    this.url         = _url;
    this.rootElement = _root;
  }
  
  /* accessors */
  
  public void setRootElement(WOElement _element) {
    this.rootElement = _element;    
  }
  public WOElement rootElement() {
    return this.rootElement;
  }

  public String addSubcomponent(String _name,
                                Map<String, WOAssociation> _assocs)
  {
    WOSubcomponentInfo info = new WOSubcomponentInfo(_name, _assocs);
    
    if (this.subcomponentInfos == null)
      this.subcomponentInfos = new HashMap<String, WOSubcomponentInfo>(16);

    /* generate unique component name */
    
    String cname = _name;
    if (this.subcomponentInfos.containsKey(cname)) {
      cname = null;
      for (int i = 0; i < 200; i++) {
        cname = _name + "[" + i + "]";
        if (!this.subcomponentInfos.containsKey(cname))
          break;
        cname = null;
      }
      if (cname == null) {
        // TODO: improve logging
        System.err.println("ERROR: failed to generate unique component name!");
        return _name; /* reuse first entry ..., not exactly a solution */
      }
    }
    
    /* register info */
    this.subcomponentInfos.put(cname, info);
    return cname /* return the name we registered the component under */;
  }
  
  public Map<String, WOSubcomponentInfo> subcomponentInfos() {
    return this.subcomponentInfos;
  }
  
  /* responder */
  
  public void takeValuesFromRequest(WORequest _rq, WOContext _ctx) {
    this.rootElement.takeValuesFromRequest(_rq, _ctx);
  }
  
  public WOActionResults invokeAction(WORequest _rq, WOContext _ctx) {
    return this.rootElement.invokeAction(_rq, _ctx);
  }
  
  public void appendToResponse(WOResponse _r, WOContext _ctx) {
    this.rootElement.appendToResponse(_r, _ctx);
  }
  
  /* description */
  
  public void appendAttributesToDescription(StringBuffer _d) {
    super.appendAttributesToDescription(_d);
    
    if (this.url != null)
      _d.append(" url=" + this.url);
    
    if (this.rootElement == null)
      _d.append(" no-root");
  }
}
