package org.opengroupware.jope.appserver.elements;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Map;

import org.opengroupware.jope.appserver.core.WOAssociation;
import org.opengroupware.jope.appserver.core.WOContext;
import org.opengroupware.jope.appserver.core.WOElement;
import org.opengroupware.jope.appserver.core.WOResponse;

/*
 * WOJavaScript
 * 
 * Generate a script tag containing JavaScript code or a link to JavaScript
 * code.
 * 
 * Sample:
 *   Script: WOJavaScript {
 *     filename = "myscript.js";
 *   }
 * 
 * Renders:
 *   <script type="text/javascript" language="JavaScript"
 *           src="/MyApp/wr/myscript.js"> </script>
 *   
 * Bindings:
 *   scriptFile    [in] - string
 *   scriptString  [in] - string
 *   hideInComment [in] - bool
 *   
 * Bindings (WOLinkGenerator for image resource):
 *   scriptSource     [in] - string
 *   src              [in] - string (^ same like above)
 *   filename         [in] - string
 *   framework        [in] - string
 *   actionClass      [in] - string
 *   directActionName [in] - string
 *   queryDictionary  [in] - Map<String,String>
 *   ?wosid           [in] - boolean (constant!)
 *   - all bindings starting with a ? are stored as query parameters.
 */
public class WOJavaScript extends WOHTMLDynamicElement {
  
  protected WOAssociation   scriptFile;
  protected WOAssociation   scriptString;
  protected WOLinkGenerator scriptSource;
  protected WOAssociation   hideInComment;
  protected WOElement       template;

  public WOJavaScript
    (String _name, Map<String, WOAssociation> _assocs, WOElement _template)
  {
    super(_name, _assocs, _template);
    
    this.scriptFile    = grabAssociation(_assocs, "scriptFile");
    this.scriptString  = grabAssociation(_assocs, "scriptString");
    this.hideInComment = grabAssociation(_assocs, "hideInComment");
    
    /* Note: 'scriptSource' is used by WO, we also support the 'src' */
    this.scriptSource = WOLinkGenerator
      .rsrcLinkGeneratorForAssociations("scriptSource", _assocs);
    
    if (this.scriptSource == null) {
      this.scriptSource = WOLinkGenerator
        .rsrcLinkGeneratorForAssociations("src", _assocs);
    }
    
    this.template = _template;
  }
  
  /* responder */

  @Override
  public void appendToResponse(WOResponse _r, WOContext _ctx) {
    if (_ctx.isRenderingDisabled())
      return;
    
    Object cursor = _ctx.cursor();
    
    /* open scripttag */

    _r.appendBeginTag("script");
    _r.appendAttribute("language", "JavaScript");
    _r.appendAttribute("type",     "text/javascript");
    
    if (this.scriptSource != null)
      _r.appendAttribute("src", this.scriptSource.fullHrefInContext(_ctx));
    
    this.appendExtraAttributesToResponse(_r, _ctx);
    // TODO: otherTagString
    
    _r.appendBeginTagEnd();
    
    /* comment if requested */
    
    boolean doHide = false;
    if (this.hideInComment != null)
      doHide = this.hideInComment.booleanValueInComponent(cursor);
    
    if (doHide) _r.appendContentString("\n<!--\n");
    
    /* tag content */
    
    if (this.scriptString != null) {
      String s = this.scriptString.stringValueInComponent(cursor);
      if (s != null) _r.appendContentHTMLString(s);
    }
    
    if (this.scriptFile != null) {
      Object v = this.scriptFile.valueInComponent(cursor);
      if (v != null) {
        RandomAccessFile f = null;
        
        try {
          if (v instanceof RandomAccessFile)
            f = (RandomAccessFile)v;
          else if (v instanceof File)
            f = new RandomAccessFile((File)v, "r");
          else if (v instanceof String)
            f = new RandomAccessFile((String)v, "r");
          else
            this.log().error("cannot process scriptfile object: " + v);
        }
        catch (FileNotFoundException e) {
          this.log().error("did not find scriptfile: " + v);
          f = null;
        }
        
        /* read file */
        
        if (f != null) {
          /* this only supports Latin-1 ... */
          try {
            String line;
            
            while ((line = f.readLine()) != null) {
              _r.appendContentHTMLString(line);
              _r.appendContentString("\n");
            }
          }
          catch (IOException e) {
            this.log().error("error reading scriptfile: " + v, e);
          }
        }
      }
    }
    
    /* close script tag */
    
    if (doHide) _r.appendContentString("\n//-->\n");
    
    if (this.template != null)
      this.template.appendToResponse(_r, _ctx);
    else {
      /* at least append a space, required by some browsers */
      _r.appendContentString(" ");
    }
    
    _r.appendEndTag("script");
  }
}
