/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Implementation of the Cocoon Forms/FlowScript integration.
 *
 * @version $Id$
 */

// Revisit this class, so it gives access to more than the value.
defineClass("org.apache.cocoon.forms.flow.javascript.ScriptableWidget");

/**
 * Create a form, given the URI of its definition file
 */
function Form(formDefinition) {
    var formMgr = null;
    var resolver = null;
    var src = null;
    var xmlAdapter = null;
    try {
        formMgr = cocoon.getComponent(Packages.org.apache.cocoon.forms.FormManager.ROLE);
        if ((typeof formDefinition) == "string" || formDefinition instanceof String) {
            resolver = cocoon.getComponent(Packages.org.apache.cocoon.environment.SourceResolver.ROLE);
            src = resolver.resolveURI(formDefinition);
            this.form = formMgr.createForm(src);
        } else {
            this.form = formMgr.createForm(formDefinition)
        }
    } finally {
        cocoon.releaseComponent(formMgr);
        if (src != null) resolver.release(src);
        cocoon.releaseComponent(resolver);
    }
    this.binding = null;
    this.eventHandler = null;
    // FIXME : hack needed because FOM doesn't provide access to the context
    this.avalonContext = formMgr.getAvalonContext();
    // TODO : do we keep this ?
    this.formWidget = new Widget(this.form);
}

Form.prototype.getModel = function() {
    return this.formWidget;
}

/**
 * Get the actual form widget (the Java object)
 */
Form.prototype.getWidget = function(name) {
    if (name != undefined) {
        throw "getWidget(id) has been deprecated.\n" +
              "Consider using getChild(id) or lookupWidget(path) instead."
    }
    return this.form;
}

/**
 * Get a child Widget (the java object) from the form via its <code>id</code>.
 */
Form.prototype.getChild = function(id) {
    return this.form.getChild(id);
}

/**
 * Get a Widget (the java object) from the form via its <code>path</code>.
 */
Form.prototype.lookupWidget = function(path) {
    return this.form.lookupWidget(path);
}

/**
 * Manages the display of a form and its validation.
 *
 * This uses some additionnal properties on the form object :
 * - "locale" : the form locale (default locale is used if not set)
 * - "cleanupHook": a function called after having sent the page displaying the form. This is equivalent
 *       to the "fun" argument of sendPageAndWait(), which allows to perform some cleanup when the pipeline
 *       has been processed. The function is called with a single parameter which is the form it is attached to.
 * - "restoreHook": a function called before processing the form when it has been submitted by
 *       the browser. This allows to restore some environment that is needed by the form processing.
 *       The function is called with a single parameter which is the form it is attached to.
 *
 * On return, the calling code can check some properties to know the form result :
 * - "isValid" : true if the form was sucessfully validated
 * - "submitId" : the id of the widget that triggered the form submit (can be null)
 *
 * @parameter uri the page uri (like in cocoon.sendPageAndWait())
 * @parameter viewdata some data for the view (like in cocoon.sendPageAndWait()).
 *            The "{FormsPipelineConfig.CFORMSKEY}" and "locale" properties are added to this object.
 * @parameter ttl the time to live of the continuation used to display the form
 */
Form.prototype.showForm = function(uri, viewdata, ttl) {
    return this.sendFormAndWait(uri, viewdata, ttl);
}

/**
 * Show form statelessly, without creating a continuation.
 *
 * @parameter uri the page uri (like in cocoon.sendPageAndWait())
 * @parameter viewdata some data for the view (like in cocoon.sendPageAndWait()).
 *            The "{FormsPipelineConfig.CFORMSKEY}" and "locale" properties are added to this object.
 */
Form.prototype.sendForm = function(uri, viewdata) {
    viewdata = this.buildViewData(viewdata)
    cocoon.sendPage(uri, viewdata);

    // Clean up after sending the page
    if (this.cleanupHook) {
        this.cleanupHook(this);
    }

    FOM_Cocoon.suicide();
}

/**
 * Process stateless form submit.
 *
 * @parameter viewdata some data for the view (like in cocoon.sendPageAndWait()).
 *            The "{FormsPipelineConfig.CFORMSKEY}" and "locale" properties are added to this object.
 */
Form.prototype.processForm = function(viewdata) {
    viewdata = this.buildViewData(viewdata)

    var formContext = new Packages.org.apache.cocoon.forms.FormContext(cocoon.request, this.locale);

    // Prematurely add the viewdata as in the object model so that event listeners can use it
    // (the same is done by cocoon.sendPage())
    // FIXME : hack needed because FOM doesn't provide access to the object model
    var objectModel = org.apache.cocoon.components.ContextHelper.getObjectModel(this.avalonContext);
    org.apache.cocoon.components.flow.FlowHelper.setContextObject(objectModel, viewdata);

    if (this.restoreHook) {
        this.restoreHook(this);
    }

    var finished = this.form.process(formContext);

    if (finished) {
        this.isValid = this.form.isValid();
        var widget = this.form.getSubmitWidget();
        // Can be null on "normal" submit
        this.submitId = widget == null ? null : widget.getId();
    }

    return finished;
}

Form.prototype.buildViewData = function(viewdata) {
    if (!viewdata) {
        viewdata = new Object();
    }

    viewdata[Packages.org.apache.cocoon.forms.transformation.FormsPipelineConfig.CFORMSKEY] = this.form;

    if (this.locale == null) {
        this.locale = java.util.Locale.getDefault();
    }

    viewdata["locale"] = this.locale;

    return viewdata
}

/**
 * Same as showForm
 */
Form.prototype.sendFormAndWait = function(uri, viewdata, ttl) {
    var finished = false;

    var comingBack = false;
    var bookmark = cocoon.createWebContinuation(ttl);

    // Attach the form to the continuation so that we can access by just knowing the continuation id
    bookmark.setAttribute("form", this.form);

    if (comingBack) {
        // We come back to the bookmark: process the form

        if (finished && cocoon.request.getParameter("cocoon-ajax-continue") != null) {
            // A request with this parameter is sent by the client upon receiving the indication
            // that Ajax interaction on the form is finished (see below).
            // We also check "finished" to ensure we won't exit showForm() because of some
            // faulty or hacked request. It's set to false, this will simply redisplay the form.
            return bookmark;
        }

        if (this.restoreHook) {
            this.restoreHook(this);
        }

        var formContext = new Packages.org.apache.cocoon.forms.FormContext(cocoon.request, this.locale);

        // Prematurely add the viewdata as in the object model so that event listeners can use it
        // (the same is done by cocoon.sendPage())
        // FIXME : hack needed because FOM doesn't provide access to the object model
        var objectModel = org.apache.cocoon.components.ContextHelper.getObjectModel(this.avalonContext);
        org.apache.cocoon.components.flow.FlowHelper.setContextObject(objectModel, viewdata);

        finished = this.form.process(formContext);

        if (finished) {
            this.isValid = this.form.isValid();
            var widget = this.form.getSubmitWidget();
            // Can be null on "normal" submit
            this.submitId = widget == null ? null : widget.getId();

            if (cocoon.request.getParameter("cocoon-ajax") != null) {
                // Ask the client to issue a new request reloading the whole page.
                // As we have nothing special to send back, so a header should be just what we need...
                // e.g. cocoon.response.setHeader("X-Cocoon-Ajax", "continue");
                //      cocoon.sendStatus(200);
                // ...but Safari doesn't consider empty responses (with content-length = 0) as
                // valid ones. So send a continue response by using directly the HttpResponse's
                // output stream. Avoiding this hack would require to put an additional pipeline
                // in the sitemap for just sending constant response, which isn't nice.
                cocoon.sendStatus(200);
                var httpResponse = objectModel.get(org.apache.cocoon.environment.http.HttpEnvironment.HTTP_RESPONSE_OBJECT);

                if (httpResponse) {
                    httpResponse.setContentType("text/xml");
                    var text = "<?xml version='1.0'?><bu:document xmlns:bu='" +
                        org.apache.cocoon.ajax.BrowserUpdateTransformer.BU_NSURI +
                        "'><bu:continue/></bu:document>";
                    httpResponse.setContentLength(text.length);
                    httpResponse.writer.print(text);
                } else {
                    // Empty response
                    cocoon.response.setHeader("Content-Length", "0");
                }

                FOM_Cocoon.suicide();
            }

            return bookmark;
        }
    }

    comingBack = true;
    viewdata = this.buildViewData(viewdata)
    cocoon.sendPage(uri, viewdata, bookmark);

    // Clean up after sending the page
    if (this.cleanupHook) {
        this.cleanupHook(this);
    }

    FOM_Cocoon.suicide();
}

Form.prototype.setValidationError = function(error) {
    this.form.setValidationError(error);
}

Form.prototype.getValidationError = function() {
    return this.form.getValidationError();
}

Form.prototype.createBinding = function(bindingURI) {
    var bindingManager = null;
    var source = null;
    var resolver = null;

    try {
        bindingManager = cocoon.getComponent(Packages.org.apache.cocoon.forms.binding.BindingManager.ROLE);
        resolver = cocoon.getComponent(Packages.org.apache.cocoon.environment.SourceResolver.ROLE);
        source = resolver.resolveURI(bindingURI);
        this.binding = bindingManager.createBinding(source);
    } finally {
        if (source != null)
            resolver.release(source);
        cocoon.releaseComponent(bindingManager);
        cocoon.releaseComponent(resolver);
    }
}

Form.prototype.load = function(object) {
    if (this.binding == null) {
        throw new Error("Binding not configured for this form.");
    }
    this.form.informStartLoadingModel();
    this.binding.loadFormFromModel(this.form, object);
    this.form.informEndLoadingModel();
}

Form.prototype.save = function(object) {
    if (this.binding == null) {
        throw new Error("Binding not configured for this form.");
    }
    this.form.informStartSavingModel();
    this.binding.saveFormToModel(this.form, object);
    this.form.informEndSavingModel();
}

Form.prototype.setAttribute = function(name, value) {
    this.form.setAttribute(name, value);
}

Form.prototype.getAttribute = function(name) {
    return this.form.getAttribute(name);
}

Form.prototype.removeAttribute = function(name) {
    this.form.removeAttribute(name);
}

Form.prototype.getXML = function() {
    if (this.xmlAdapter == null)
        this.xmlAdapter = new Packages.org.apache.cocoon.forms.util.XMLAdapter(this.form);

    return this.xmlAdapter;
}

Form.prototype.loadXML = function(uri) {
    var source = null;
    var resolver = null;

    try {
        resolver = cocoon.getComponent(Packages.org.apache.cocoon.environment.SourceResolver.ROLE);
        source = resolver.resolveURI(uri);
        // Disambiguate toSAX method: Pick the one with Sosurce argument.
        Packages.org.apache.cocoon.components.source.SourceUtil["toSAX(org.apache.excalibur.source.Source,org.xml.sax.ContentHandler)"](source, this.getXML())
    } finally {
        if (source != null) {
            resolver.release(source);
        }
        cocoon.releaseComponent(resolver);
    }
}

Form.prototype.saveXML = function(uri) {
    var source = null;
    var resolver = null;
    var outputStream = null;
    try {
        resolver = cocoon.getComponent(Packages.org.apache.cocoon.environment.SourceResolver.ROLE);
        source = resolver.resolveURI(uri);

        var tf = Packages.javax.xml.transform.TransformerFactory.newInstance();

        if (source instanceof Packages.org.apache.excalibur.source.ModifiableSource
            && tf.getFeature(Packages.javax.xml.transform.sax.SAXTransformerFactory.FEATURE)) {

            outputStream = source.getOutputStream();
            var transformerHandler = tf.newTransformerHandler();
            var transformer = transformerHandler.getTransformer();
            transformer.setOutputProperty(Packages.javax.xml.transform.OutputKeys.INDENT, "true");
            transformer.setOutputProperty(Packages.javax.xml.transform.OutputKeys.METHOD, "xml");
            transformerHandler.setResult(new Packages.javax.xml.transform.stream.StreamResult(outputStream));
            this.getXML().toSAX(transformerHandler);
        } else {
            throw new Packages.org.apache.cocoon.ProcessingException("Cannot write to source " + uri);
        }

    } finally {
        if (source != null) {
            resolver.release(source);
        }
        cocoon.releaseComponent(resolver);

        if (outputStream != null) {
            try {
                outputStream.flush();
                outputStream.close();
            } catch (error) {
                cocoon.log.error("Could not flush/close outputstream: " + error);
            }
        }
    }
}

function handleForm() {
    // get the form definition
    var def = cocoon.parameters["definitionURI"];
    if (def == null) {
        if (cocoon.parameters["form-definition"] != null) {
            cocoon.log.warn("the form-definition parameter in handleForm has changed to definitionURI");
            def = cocoon.parameters["form-definition"];
        } else {
            throw "Definition not configured for this form.";
        }
    }
    // create the Form
    var form = new Form(def);
    // set the binding on the form if there is one
    var bindingURI = cocoon.parameters["bindingURI"];

    if (bindingURI != null) {
        form.createBinding(bindingURI);
    }

    // get the function to call to handle the form
    var funcName = cocoon.parameters["function"];
    var func = this[funcName];

    // check the function exists
    if (!func) {
        throw "Function \"" + funcName + "\" is not defined.";
    } else if (!(func instanceof Function)) {
        throw "\"" + funcName + "\" is not a function.";
    }

    // call the function
    func.apply(this, [form]);
}
