/*******************************************************************************
 * 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.ofbiz.content.webapp.ftl;

import java.io.IOException;
import java.io.Writer;
import java.sql.Timestamp;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import javolution.util.FastList;
import javolution.util.FastMap;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.base.util.template.FreeMarkerWorker;
import org.ofbiz.content.content.ContentServicesComplex;
import org.ofbiz.content.content.ContentWorker;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.minilang.MiniLangException;
import org.ofbiz.webapp.ftl.LoopWriter;

import freemarker.core.Environment;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateTransformModel;
import freemarker.template.TransformControl;

/**
 * LimitedSubContentCacheTransform - Freemarker Transform for URLs (links)
 */
public class LimitedSubContentCacheTransform implements TemplateTransformModel {

    public static final String module = LimitedSubContentCacheTransform.class.getName();

    public static final String [] upSaveKeyNames = {"globalNodeTrail"};
    public static final String [] saveKeyNames = {"contentId", "subContentId", "entityList", "entityIndex", "subDataResourceTypeId", "mimeTypeId", "whenMap", "locale",  "entityList", "viewSize", "viewIndex", "highIndex", "lowIndex", "listSize", "wrapTemplateId", "encloseWrapText", "nullThruDatesOnly", "globalNodeTrail", "outputIndex"};

    /**
     * @deprecated use FreeMarkerWorker.getWrappedObject()
     * A wrapper for the FreeMarkerWorker version.
     */
    @Deprecated
    public static Object getWrappedObject(String varName, Environment env) {
        return FreeMarkerWorker.getWrappedObject(varName, env);
    }

    /**
     * @deprecated use FreeMarkerWorker.getArg()
     */
    @Deprecated
    public static String getArg(Map<String, ? extends Object> args, String key, Environment env) {
        return FreeMarkerWorker.getArg(args, key, env);
    }

    /**
     * @deprecated use FreeMarkerWorker.getArg()
     */
    @Deprecated
    public static String getArg(Map<String, ? extends Object> args, String key, Map<String, ? extends Object> ctx) {
        return FreeMarkerWorker.getArg(args, key, ctx);
    }

    @SuppressWarnings("unchecked")
    public Writer getWriter(final Writer out, Map args) {
        //Profiler.begin("Limited");
        final StringBuilder buf = new StringBuilder();
        final Environment env = Environment.getCurrentEnvironment();
        final Map<String, Object> templateRoot = FreeMarkerWorker.createEnvironmentMap(env);
        final Delegator delegator = FreeMarkerWorker.getWrappedObject("delegator", env);
        final HttpServletRequest request = FreeMarkerWorker.getWrappedObject("request", env);
        FreeMarkerWorker.getSiteParameters(request, templateRoot);
        final Map<String, Object> savedValuesUp = FastMap.newInstance();
        FreeMarkerWorker.saveContextValues(templateRoot, upSaveKeyNames, savedValuesUp);
        final Map<String, Object> savedValues = FastMap.newInstance();
        FreeMarkerWorker.overrideWithArgs(templateRoot, args);

        String contentAssocTypeId = (String) templateRoot.get("contentAssocTypeId");
        if (UtilValidate.isEmpty(contentAssocTypeId)) {
            contentAssocTypeId = "SUB_CONTENT";
            templateRoot.put("contentAssocTypeId ", contentAssocTypeId);
        }

        final Map<String, GenericValue> pickedEntityIds = FastMap.newInstance();
        List<String> assocTypes = StringUtil.split(contentAssocTypeId, "|");

        String contentPurposeTypeId = (String) templateRoot.get("contentPurposeTypeId");
        List<String> purposeTypes = StringUtil.split(contentPurposeTypeId, "|");
        templateRoot.put("purposeTypes", purposeTypes);
        Locale locale = (Locale) templateRoot.get("locale");
        if (locale == null) {
            locale = Locale.getDefault();
            templateRoot.put("locale", locale);
        }

        Map<String, Object> whenMap = FastMap.newInstance();
        whenMap.put("followWhen", templateRoot.get("followWhen"));
        whenMap.put("pickWhen", templateRoot.get("pickWhen"));
        whenMap.put("returnBeforePickWhen", templateRoot.get("returnBeforePickWhen"));
        whenMap.put("returnAfterPickWhen", templateRoot.get("returnAfterPickWhen"));
        templateRoot.put("whenMap", whenMap);

        String fromDateStr = (String) templateRoot.get("fromDateStr");
        Timestamp fromDate = null;
        if (UtilValidate.isNotEmpty(fromDateStr)) {
            fromDate = UtilDateTime.toTimestamp(fromDateStr);
        }
        if (fromDate == null) {
            fromDate = UtilDateTime.nowTimestamp();
        }

        String limitSize = (String) templateRoot.get("limitSize");
        final int returnLimit = Integer.parseInt(limitSize);
        // limitMode will be "random" to begin with
        // String limitMode = (String) templateRoot.get("limitMode");
        // final GenericValue userLogin = FreeMarkerWorker.getWrappedObject("userLogin", env);
        // List<Map<String, ? extends Object>> globalNodeTrail = UtilGenerics.checkList(templateRoot.get("globalNodeTrail"));
        // String strNullThruDatesOnly = (String) templateRoot.get("nullThruDatesOnly");
        // Boolean nullThruDatesOnly = (strNullThruDatesOnly != null && strNullThruDatesOnly.equalsIgnoreCase("true")) ? Boolean.TRUE : Boolean.FALSE;
        String orderBy = (String) templateRoot.get("orderBy");
        
        // NOTE this was looking for subContentId, but that doesn't make ANY sense, so changed to contentId
        String contentId = (String) templateRoot.get("contentId");

        templateRoot.put("contentId", null);
        templateRoot.put("subContentId", null);

        // final String contentIdTo = contentId;

        Map<String, Object> results = null;
        //if (Debug.infoOn()) Debug.logInfo("in LimitedSubContentCache(0), assocTypes ." + assocTypes, module);
        String contentAssocPredicateId = (String) templateRoot.get("contentAssocPredicateId");
        try {
            results = ContentServicesComplex.getAssocAndContentAndDataResourceCacheMethod(delegator, contentId, null, "From", fromDate, null, assocTypes, null, Boolean.TRUE, contentAssocPredicateId, orderBy);
        } catch (MiniLangException e) {
            throw new RuntimeException(e.getMessage(), e);
        } catch (GenericEntityException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        List<GenericValue> longList = UtilGenerics.checkList(results.get("entityList"));
        templateRoot.put("entityList", longList);
        //if (Debug.infoOn()) Debug.logInfo("in limited, longList:" + longList , "");

        return new LoopWriter(out) {

            @Override
            public void write(char cbuf[], int off, int len) {
                buf.append(cbuf, off, len);
                //StringBuilder ctxBuf = (StringBuilder) templateRoot.get("buf");
                //ctxBuf.append(cbuf, off, len);
            }

            @Override
            public void flush() throws IOException {
                out.flush();
            }

            @Override
            public int onStart() throws TemplateModelException, IOException {
                // List<Map<String, ? extends Object>> globalNodeTrail = UtilGenerics.checkList(templateRoot.get("globalNodeTrail"));
                // String trailCsv = ContentWorker.nodeTrailToCsv(globalNodeTrail);
                boolean inProgress = false;
                //if (Debug.infoOn()) Debug.logInfo("in limited, returnLimit:" + returnLimit , "");
                //if (Debug.infoOn()) Debug.logInfo("in limited, pickedEntityIds:" + pickedEntityIds , "");
                if (pickedEntityIds.size() < returnLimit) {
                    inProgress = getNextMatchingEntity(templateRoot, delegator, env);
                }
                FreeMarkerWorker.saveContextValues(templateRoot, saveKeyNames, savedValues);
                if (inProgress) {
                    return TransformControl.EVALUATE_BODY;
                } else {
                    return TransformControl.SKIP_BODY;
                }
            }

            @Override
            public int afterBody() throws TemplateModelException, IOException {
                FreeMarkerWorker.reloadValues(templateRoot, savedValues, env);
                List<Map<String, ? extends Object>> list = UtilGenerics.checkList(templateRoot.get("globalNodeTrail"));
                List<Map<String, ? extends Object>> subList = list.subList(0, list.size() - 1);
                templateRoot.put("globalNodeTrail", subList);
                env.setVariable("globalNodeTrail", FreeMarkerWorker.autoWrap(subList, env));

                //if (Debug.infoOn()) Debug.logInfo("highIndex(2):" + highIndexInteger , "");
                //if (Debug.infoOn()) Debug.logInfo("in limited, returnLimit(2):" + returnLimit , "");
                //if (Debug.verboseOn()) Debug.logVerbose("in limited, pickedEntityIds(2):" + pickedEntityIds , "");
                boolean inProgress = false;
                if (pickedEntityIds.size() < returnLimit) {
                    inProgress = getNextMatchingEntity(templateRoot, delegator, env);
                }

                FreeMarkerWorker.saveContextValues(templateRoot, saveKeyNames, savedValues);
                if (inProgress) {
                    return TransformControl.REPEAT_EVALUATION;
                } else {
                    return TransformControl.END_EVALUATION;
                }
            }

            @Override
            public void close() throws IOException {
                FreeMarkerWorker.reloadValues(templateRoot, savedValuesUp, env);
                String wrappedContent = buf.toString();
                out.write(wrappedContent);
                //try {
                //Profiler.end("Limited");
                //FileOutputStream fw = new FileOutputStream(FileUtil.getFile("/usr/local/agi/ofbiz/hot-deploy/sfmp/misc/profile.data"));
                //Profiler.print(fw);
                //fw.close();
                //} catch (IOException e) {
                //Debug.logError("[PROFILER] " + e.getMessage(),"");
                //}
            }

            public boolean prepCtx(Delegator delegator, Map<String, Object> ctx, Environment env, GenericValue view) throws GeneralException {
                // String dataResourceId = (String) view.get("drDataResourceId");
                String subContentIdSub = (String) view.get("contentId");
                // This order is taken so that the dataResourceType can be overridden in the transform arguments.
                String subDataResourceTypeId = (String) ctx.get("subDataResourceTypeId");
                if (UtilValidate.isEmpty(subDataResourceTypeId)) {
                    subDataResourceTypeId = (String) view.get("drDataResourceTypeId");
                    // TODO: If this value is still empty then it is probably necessary to get a value from
                    // the parent context. But it will already have one and it is the same context that is
                    // being passed.
                }

                String mimeTypeId = ContentWorker.getMimeTypeId(delegator, view, ctx);
                Map<String, Object> trailNode = ContentWorker.makeNode(view);
                Map<String, Object> whenMap = UtilGenerics.checkMap(ctx.get("whenMap"));
                Locale locale = (Locale) ctx.get("locale");
                if (locale == null) {
                    locale = Locale.getDefault();
                }
                GenericValue assocContent = null;
                ContentWorker.checkConditions(delegator, trailNode, assocContent, whenMap);
                Boolean isReturnBeforeObj = (Boolean) trailNode.get("isReturnBefore");
                // Boolean isReturnAfterObj = (Boolean) trailNode.get("isReturnAfter");
                Boolean isPickObj = (Boolean) trailNode.get("isPick");
                Boolean isFollowObj = (Boolean) trailNode.get("isFollow");
                //if (Debug.infoOn()) Debug.logInfo("in LimitedSubContentCache, isReturnBeforeObj" + isReturnBeforeObj + " isPickObj:" + isPickObj + " isFollowObj:" + isFollowObj + " isReturnAfterObj:" + isReturnAfterObj, module);
                if ((isReturnBeforeObj == null || !isReturnBeforeObj.booleanValue()) && ((isPickObj != null &&
                        isPickObj.booleanValue()) || (isFollowObj != null && isFollowObj.booleanValue()))) {
                    List<Map<String, ? extends Object>> globalNodeTrail = UtilGenerics.checkList(ctx.get("globalNodeTrail"));
                    if (globalNodeTrail == null) {
                        globalNodeTrail = FastList.newInstance();
                    }
                    globalNodeTrail.add(trailNode);
                    ctx.put("globalNodeTrail", globalNodeTrail);
                    String csvTrail = ContentWorker.nodeTrailToCsv(globalNodeTrail);
                    ctx.put("nodeTrailCsv", csvTrail);
                    //if (Debug.infoOn()) Debug.logInfo("prepCtx, csvTrail(2):" + csvTrail, "");
                    int indentSz = globalNodeTrail.size();
                    ctx.put("indent", Integer.valueOf(indentSz));

                    ctx.put("subDataResourceTypeId", subDataResourceTypeId);
                    ctx.put("mimeTypeId", mimeTypeId);
                    ctx.put("subContentId", subContentIdSub);
                    ctx.put("content", view);

                    env.setVariable("subDataResourceTypeId", FreeMarkerWorker.autoWrap(subDataResourceTypeId, env));
                    env.setVariable("indent", FreeMarkerWorker.autoWrap(Integer.valueOf(indentSz), env));
                    env.setVariable("nodeTrailCsv", FreeMarkerWorker.autoWrap(csvTrail, env));
                    env.setVariable("globalNodeTrail", FreeMarkerWorker.autoWrap(globalNodeTrail, env));
                    env.setVariable("content", FreeMarkerWorker.autoWrap(view, env));
                    env.setVariable("mimeTypeId", FreeMarkerWorker.autoWrap(mimeTypeId, env));
                    env.setVariable("subContentId", FreeMarkerWorker.autoWrap(subContentIdSub, env));
                    return true;
                } else {
                    return false;
                }
            }

            public GenericValue getRandomEntity() {
                GenericValue pickEntity = null;
                List<GenericValue> lst = UtilGenerics.checkList(templateRoot.get("entityList"));
                if (Debug.verboseOn()) Debug.logVerbose("in limited, lst:" + lst, "");

                while (pickEntity == null && lst.size() > 0) {
                    double randomValue = Math.random();
                    //if (Debug.infoOn()) Debug.logInfo("in limited, randomValue:" + randomValue , "");
                    int idx = (int) (lst.size() * randomValue);
                    //if (Debug.infoOn()) Debug.logInfo("in limited, idx:" + idx , "");
                    pickEntity = lst.get(idx);
                    String pickEntityId = pickEntity.getString("contentId");
                    if (pickedEntityIds.get(pickEntityId) == null) {
                        pickedEntityIds.put(pickEntityId, pickEntity);
                        lst.remove(idx);
                    } else {
                        pickEntity = null;
                    }
                }
                return pickEntity;
            }

            public boolean getNextMatchingEntity(Map<String, Object> templateRoot, Delegator delegator, Environment env) throws IOException {
                boolean matchFound = false;
                GenericValue pickEntity = getRandomEntity();

                while (pickEntity != null && !matchFound) {
                    try {
                        matchFound = prepCtx(delegator, templateRoot, env, pickEntity);
                    } catch (GeneralException e) {
                        throw new IOException(e.getMessage());
                    }
                    if (!matchFound)
                        pickEntity = getRandomEntity();
                }
                return matchFound;
            }
        };
    }
}
