/*
 * 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.
 */
package org.apache.sling.scripting.javascript.wrapper;

import java.io.PrintWriter;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;

import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.scripting.javascript.helper.SlingWrapper;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Wrapper;

public class ScriptablePrintWriter extends ScriptableObject implements SlingWrapper {

    public static final String CLASSNAME = "PrintWriter";
    public static final Class<?> [] WRAPPED_CLASSES = { PrintWriter.class };

    private PrintWriter writer;

    // the locale to use for printf
    private Locale locale;

    public ScriptablePrintWriter() {
    }

    public ScriptablePrintWriter(PrintWriter writer) {
        this.writer = writer;
    }

    public void jsConstructor(Object res) {
        this.writer = (PrintWriter) res;
    }

    @Override
    public String getClassName() {
        return CLASSNAME;
    }

    public Class<?> [] getWrappedClasses() {
        return WRAPPED_CLASSES;
    }
    
    // print args to writer if any
    // this method supports write(Object)
    public static void jsFunction_write(Context cx, Scriptable thisObj,
            Object[] args, Function funObj) {
        print(thisObj, args);
    }

    // print args to writer if any
    // this method supports print(Object)
    public static void jsFunction_print(Context cx, Scriptable thisObj,
            Object[] args, Function funObj) {
        print(thisObj, args);
    }

    // print a formatted string to the writer. The first arg is used as the
    // formatter Locale if it is a Locale instance. The next argument is the
    // format string followed by format arguments.
    // This method supports printf(Locale, String, Object...) and
    // printf(String, Object...)
    public static void jsFunction_printf(Context cx, Scriptable thisObj,
            Object[] args, Function funObj) {

        if (args.length > 0) {

            // the index of the next argument to consider
            int nextIdx = 0;

            // the local for printf
            Locale locale = null;

            if (args[nextIdx] instanceof Locale) {

                // the Locale is the first argument, use it an increment idx
                locale = (Locale) args[nextIdx];
                nextIdx++;

            } else {

                // get the per-HTTP request local or the default locale
                locale = ((ScriptablePrintWriter) thisObj).getLocale();
            }

            // only continue, if there is at least an other argument
            // containing the format string
            if (args.length > nextIdx) {

                // the format string
                String format = ScriptRuntime.toString(args[nextIdx]);

                // arguments starting after that are formatting arguments
                nextIdx++;
                Object[] formatArgs = new Object[args.length - nextIdx];
                System.arraycopy(args, nextIdx, formatArgs, 0,
                    formatArgs.length);

                // now get the writer and call printf
                PrintWriter writer = ((ScriptablePrintWriter) thisObj).writer;
                writer.printf(locale, format, formatArgs);
            }
        }
    }

    // print args to the writer (if any) and append a line feed
    // this method supports println(Object)
    public static void jsFunction_println(Context cx, Scriptable thisObj,
            Object[] args, Function funObj) {
        print(thisObj, args).println();
    }

    // ---------- Wrapper interface --------------------------------------------

    // returns the wrapped print writer
    public Object unwrap() {
        return writer;
    }

    // ---------- internal helper ----------------------------------------------

    // print all arguments as strings to the writer
    private static PrintWriter print(Object thisObj, Object[] args) {
        PrintWriter writer = ((ScriptablePrintWriter) thisObj).writer;
        for (Object arg : args) {
            writer.print(ScriptRuntime.toString(arg));
        }
        return writer;
    }

    // helper method to return the locale to use for this instance:
    //    - if the global scope has a "request" object which is a
    //      HttpServletRequest, we call getLocale() on that object
    //    - Otherwise or if getLocale returns null, we use the platform default
    private Locale getLocale() {
        if (locale == null) {
            
            try {
                // check whether we have a request object which has the locale
                Object reqObj = ScriptRuntime.name(Context.getCurrentContext(),
                    this, SlingBindings.REQUEST);
                if (reqObj instanceof Wrapper) {
                    Object wrapped = ((Wrapper) reqObj).unwrap();
                    if (wrapped instanceof HttpServletRequest) {
                        locale = ((HttpServletRequest) wrapped).getLocale();
                    }
                }
            } catch (Exception e) {
                // ignore any exceptions resulting from this and use default
            }

            // default, if the no request locale or no request is available
            if (locale == null) {
                locale = Locale.getDefault();
            }

        }

        return locale;
    }
}
