/*
 * Copyright (C) 2007 Helge Hess
 *
 * This file is part of JOPE.
 *
 * JOPE 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, or (at your option) any later version.
 *
 * JOPE 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.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with JOPE; see the file COPYING. If not, write to the Free Software
 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
package org.opengroupware.jope.jsapp;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;

import org.opengroupware.jope.appserver.core.WOApplication;
import org.opengroupware.jope.appserver.core.WOComponentDefinition;
import org.opengroupware.jope.appserver.core.WOResourceManager;

/**
 * JSResourceManager
 * <p>
 * This resource manager looks for JS components in the given root directory.
 */
public class JSResourceManager extends WOResourceManager {
  
  WOApplication app;
  File root;

  public JSResourceManager(WOApplication _app, File _root, boolean caching) {
    super(caching);
    this.app  = _app;
    this.root = _root;
  }

  
  /* cache */
  
  protected File findJSComponentWithName(String _name) {
    if (_name == null)
      return null;
    
    File f = new File(this.root, _name + ".wo");
    if (f == null)
      return null;
    
    return f.exists() ? f : null;
  }
  
  protected Class classForScriptedComponent(String _name, File _file) {
    // TBD: find a way which lets the WOComponents select their superclass
    return JSComponent.class;
  }
  
  
  /* class lookup */

  @Override
  public Class lookupComponentClass(String _name) {
    if (this.findJSComponentWithName(_name) != null)
      return this.classForScriptedComponent(_name, null /* TBD */);
    
    return super.lookupComponentClass(_name);
  }
  
  @Override
  public Class lookupDirectActionClass(String _name) {
    if (this.findJSComponentWithName(_name) != null)
      return this.classForScriptedComponent(_name, null /* TBD */);
    
    // TBD: JS direct actions
    return super.lookupDirectActionClass(_name);
  }
  
  
  /* component lookup */
  
  @Override
  public WOComponentDefinition definitionForComponent
    (String _name, String[] _langs, WOResourceManager _clsctx)
  {
    File compWrapper = this.findJSComponentWithName(_name);
    if (compWrapper != null)
      return this.definitionForJSComponent(_name, compWrapper, _langs, _clsctx);
    
    return super.definitionForComponent(_name, _langs, _clsctx);
  }
  
  
  private static URL fileAsURL(File _f) {
    if (_f == null)
      return null;
    if (!_f.isFile())
      return null;
    try { return _f.toURL(); }
    catch (MalformedURLException e) { };
    return null;
  }

  public WOComponentDefinition definitionForJSComponent
    (String _name, File _wrapper, String[] _langs, WOResourceManager _rm)
  {
    // TBD: we might support some config, eg to specify a DIFFERENT root
    //      class (not JSComponent)
    if (_wrapper == null)
      return null;
    
    
    /* find template and wod */
    
    URL templateData = null;
    URL wodData = null;
    
    templateData = fileAsURL(new File(_wrapper, "Component.html"));
    if (templateData == null)
      templateData = fileAsURL(new File(_wrapper, _name + ".html"));

    wodData = fileAsURL(new File(_wrapper, "Component.wod"));
    if (wodData == null)
      wodData = fileAsURL(new File(_wrapper, _name + ".wod"));

    // its not strictly necessary that the component has a script
    File jsData = new File(_wrapper, "Component.js");
    if (jsData == null || !jsData.isFile()) {
      jsData = new File(_wrapper, _name + ".js");
      if (jsData != null && !jsData.isFile())
        jsData = null;
    }
    
    
    /* def */

    WOComponentDefinition cdef = new JSComponentDefinition
      (_name, this.classForScriptedComponent(_name, _wrapper), jsData);

    /* load it */

    if (!cdef.load("WOWrapper", templateData, wodData, _rm)) {
      log.error("failed to load template.");
      return null;
    }
    return cdef;
    
  }
}
