/*******************************************************************************
 * 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.survey;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

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.UtilDateTime;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.content.data.DataResourceWorker;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.util.EntityQuery;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ModelService;
import org.ofbiz.service.ServiceUtil;

import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.AcroFields;
import com.lowagie.text.pdf.PdfDictionary;
import com.lowagie.text.pdf.PdfName;
import com.lowagie.text.pdf.PdfObject;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;
import com.lowagie.text.pdf.PdfWriter;


/**
 * PdfSurveyServices Class
 */

public class PdfSurveyServices {

    public static final String module = PdfSurveyServices.class.getName();
    public static final String resource = "ContentUiLabels";

    /**
     *
     */
    public static Map<String, Object> buildSurveyFromPdf(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Locale locale = (Locale) context.get("locale");
        Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
        String surveyId = null;
        try {
            String surveyName = (String) context.get("surveyName");
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ByteBuffer byteBuffer = getInputByteBuffer(context, delegator);
            PdfReader pdfReader = new PdfReader(byteBuffer.array());
            PdfStamper pdfStamper = new PdfStamper(pdfReader, os);
            AcroFields acroFields = pdfStamper.getAcroFields();
            Map<String, Object> acroFieldMap = UtilGenerics.checkMap(acroFields.getFields());

            String contentId = (String) context.get("contentId");
            GenericValue survey = null;
            surveyId = (String) context.get("surveyId");
            if (UtilValidate.isEmpty(surveyId)) {
                survey = delegator.makeValue("Survey", UtilMisc.toMap("surveyName", surveyName));
                survey.set("surveyId", surveyId);
                survey.set("allowMultiple", "Y");
                survey.set("allowUpdate", "Y");
                survey = delegator.createSetNextSeqId(survey);
                surveyId = survey.getString("surveyId");
            }

            // create a SurveyQuestionCategory to put the questions in
            Map<String, Object> createCategoryResultMap = dispatcher.runSync("createSurveyQuestionCategory", UtilMisc.<String, Object>toMap("description", "From AcroForm in Content [" + contentId + "] for Survey [" + surveyId + "]", "userLogin", userLogin));
            String surveyQuestionCategoryId = (String) createCategoryResultMap.get("surveyQuestionCategoryId");

            pdfStamper.setFormFlattening(true);
            for (String fieldName : acroFieldMap.keySet()) {
                AcroFields.Item item = acroFields.getFieldItem(fieldName);
                int type = acroFields.getFieldType(fieldName);
                String value = acroFields.getField(fieldName);
                Debug.logInfo("fieldName:" + fieldName + "; item: " + item + "; value: " + value, module);

                GenericValue surveyQuestion = delegator.makeValue("SurveyQuestion", UtilMisc.toMap("question", fieldName));
                String surveyQuestionId = delegator.getNextSeqId("SurveyQuestion");
                surveyQuestion.set("surveyQuestionId", surveyQuestionId);
                surveyQuestion.set("surveyQuestionCategoryId", surveyQuestionCategoryId);

                if (type == AcroFields.FIELD_TYPE_TEXT) {
                    surveyQuestion.set("surveyQuestionTypeId", "TEXT_SHORT");
                } else if (type == AcroFields.FIELD_TYPE_RADIOBUTTON) {
                    surveyQuestion.set("surveyQuestionTypeId", "OPTION");
                } else if (type == AcroFields.FIELD_TYPE_LIST || type == AcroFields.FIELD_TYPE_COMBO) {
                    surveyQuestion.set("surveyQuestionTypeId", "OPTION");
                    // TODO: handle these specially with the acroFields.getListOptionDisplay (and getListOptionExport?)
                    /*String[] listOptionDisplayArray = acroFields.getListOptionDisplay(fieldName);
                    String[] listOptionExportArray = acroFields.getListOptionExport(fieldName);
                    Debug.logInfo("listOptionDisplayArray: " + listOptionDisplayArray + "; listOptionExportArray: " + listOptionExportArray, module);*/
                } else {
                    surveyQuestion.set("surveyQuestionTypeId", "TEXT_SHORT");
                    Debug.logWarning("Building Survey from PDF, fieldName=[" + fieldName + "]: don't know how to handle field type: " + type + "; defaulting to short text", module);
                }

                // ==== create a good sequenceNum based on tab order or if no tab order then the page location

                Integer tabPage = item.getPage(0);
                Integer tabOrder = item.getTabOrder(0);
                Debug.logInfo("tabPage=" + tabPage + ", tabOrder=" + tabOrder, module);

                //array of float  multiple of 5. For each of this groups the values are: [page, llx, lly, urx, ury]
                float[] fieldPositions = acroFields.getFieldPositions(fieldName);
                float fieldPage = fieldPositions[0];
                float fieldLlx = fieldPositions[1];
                float fieldLly = fieldPositions[2];
                float fieldUrx = fieldPositions[3];
                float fieldUry = fieldPositions[4];
                Debug.logInfo("fieldPage=" + fieldPage + ", fieldLlx=" + fieldLlx + ", fieldLly=" + fieldLly + ", fieldUrx=" + fieldUrx + ", fieldUry=" + fieldUry, module);

                Long sequenceNum = null;
                if (tabPage != null && tabOrder != null) {
                    sequenceNum = Long.valueOf(tabPage.intValue() * 1000 + tabOrder.intValue());
                    Debug.logInfo("tabPage=" + tabPage + ", tabOrder=" + tabOrder + ", sequenceNum=" + sequenceNum, module);
                } else if (fieldPositions.length > 0) {
                    sequenceNum = Long.valueOf((long) fieldPage * 10000 + (long) fieldLly * 1000 + (long) fieldLlx);
                    Debug.logInfo("fieldPage=" + fieldPage + ", fieldLlx=" + fieldLlx + ", fieldLly=" + fieldLly + ", fieldUrx=" + fieldUrx + ", fieldUry=" + fieldUry + ", sequenceNum=" + sequenceNum, module);
                }

                // TODO: need to find something better to put into these fields...
                String annotation = null;
                for (int k = 0; k < item.size(); ++k) {
                    PdfDictionary dict = item.getWidget(k);

                    // if the "/Type" value is "/Annot", then get the value of "/TU" for the annotation

                    /* Interesting... this doesn't work, I guess we have to iterate to find the stuff...
                    PdfObject typeValue = dict.get(new PdfName("/Type"));
                    if (typeValue != null && "/Annot".equals(typeValue.toString())) {
                        PdfObject tuValue = dict.get(new PdfName("/TU"));
                        annotation = tuValue.toString();
                    }
                    */

                    PdfObject typeValue = null;
                    PdfObject tuValue = null;

                    Set<PdfName> dictKeys = UtilGenerics.checkSet(dict.getKeys());
                    for (PdfName dictKeyName : dictKeys) {
                        PdfObject dictObject = dict.get(dictKeyName);

                        if ("/Type".equals(dictKeyName.toString())) {
                            typeValue = dictObject;
                        } else if ("/TU".equals(dictKeyName.toString())) {
                            tuValue = dictObject;
                        }
                        //Debug.logInfo("AcroForm widget fieldName[" + fieldName + "] dictKey[" + dictKeyName.toString() + "] dictValue[" + dictObject.toString() + "]", module);
                    }
                    if (tuValue != null && typeValue != null && "/Annot".equals(typeValue.toString())) {
                        annotation = tuValue.toString();
                    }
                }

                surveyQuestion.set("description", fieldName);
                if (UtilValidate.isNotEmpty(annotation)) {
                    surveyQuestion.set("question", annotation);
                } else {
                    surveyQuestion.set("question", fieldName);
                }

                GenericValue surveyQuestionAppl = delegator.makeValue("SurveyQuestionAppl", UtilMisc.toMap("surveyId", surveyId, "surveyQuestionId", surveyQuestionId));
                surveyQuestionAppl.set("fromDate", nowTimestamp);
                surveyQuestionAppl.set("externalFieldRef", fieldName);

                if (sequenceNum != null) {
                    surveyQuestionAppl.set("sequenceNum", sequenceNum);
                }

                surveyQuestion.create();
                surveyQuestionAppl.create();
            }
            pdfStamper.close();
            if (UtilValidate.isNotEmpty(contentId)) {
                survey = EntityQuery.use(delegator).from("Survey").where("surveyId", surveyId).queryOne();
                survey.set("acroFormContentId", contentId);
                survey.store();
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, "Error generating PDF: " + e.toString(), module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentPDFGeneratingError", UtilMisc.toMap("errorString", e.toString()), locale));
        } catch (GeneralException e) {
            Debug.logError(e, "Error generating PDF: " + e.getMessage(), module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentPDFGeneratingError", UtilMisc.toMap("errorString", e.getMessage()), locale));
        } catch (Exception e) {
            Debug.logError(e, "Error generating PDF: " + e.toString(), module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentPDFGeneratingError", UtilMisc.toMap("errorString", e.toString()), locale));
        }

        Map<String, Object> results = ServiceUtil.returnSuccess();
        results.put("surveyId", surveyId);
        return results;
    }

    /**
     *
     */
    public static Map<String, Object> buildSurveyResponseFromPdf(DispatchContext dctx, Map<String, ? extends Object> context) {
        String surveyResponseId = null;
        Locale locale = (Locale) context.get("locale");
        try {
            Delegator delegator = dctx.getDelegator();
            String partyId = (String)context.get("partyId");
            String surveyId = (String)context.get("surveyId");
            //String contentId = (String)context.get("contentId");
            surveyResponseId = (String)context.get("surveyResponseId");
            if (UtilValidate.isNotEmpty(surveyResponseId)) {
                GenericValue surveyResponse = EntityQuery.use(delegator).from("SurveyResponse").where("surveyResponseId", surveyResponseId).queryOne();
                if (surveyResponse != null) {
                    surveyId = surveyResponse.getString("surveyId");
                }
            } else {
                surveyResponseId = delegator.getNextSeqId("SurveyResponse");
                GenericValue surveyResponse = delegator.makeValue("SurveyResponse", UtilMisc.toMap("surveyResponseId", surveyResponseId, "surveyId", surveyId, "partyId", partyId));
                surveyResponse.set("responseDate", UtilDateTime.nowTimestamp());
                surveyResponse.set("lastModifiedDate", UtilDateTime.nowTimestamp());
                surveyResponse.create();
            }

            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ByteBuffer byteBuffer = getInputByteBuffer(context, delegator);
            PdfReader r = new PdfReader(byteBuffer.array());
            PdfStamper s = new PdfStamper(r,os);
            AcroFields fs = s.getAcroFields();
            Map<String, Object> hm = UtilGenerics.checkMap(fs.getFields());
            s.setFormFlattening(true);
            for (String fieldName : hm.keySet()) {
                //AcroFields.Item item = fs.getFieldItem(fieldName);
                //int type = fs.getFieldType(fieldName);
                String value = fs.getField(fieldName);
                GenericValue surveyQuestionAndAppl = EntityQuery.use(delegator).from("SurveyQuestionAndAppl")
                        .where("surveyId", surveyId,
                                "externalFieldRef", fieldName)
                        .queryFirst();
                if (surveyQuestionAndAppl == null) {
                    Debug.logInfo("No question found for surveyId:" + surveyId + " and externalFieldRef:" + fieldName, module);
                    continue;
                }

                String surveyQuestionId = (String)surveyQuestionAndAppl.get("surveyQuestionId");
                String surveyQuestionTypeId = (String)surveyQuestionAndAppl.get("surveyQuestionTypeId");
                GenericValue surveyResponseAnswer = delegator.makeValue("SurveyResponseAnswer", UtilMisc.toMap("surveyResponseId", surveyResponseId, "surveyQuestionId", surveyQuestionId));
                if (surveyQuestionTypeId ==null || surveyQuestionTypeId.equals("TEXT_SHORT")) {
                    surveyResponseAnswer.set("textResponse", value);
                }

                delegator.create(surveyResponseAnswer);
            }
            s.close();
        } catch (GenericEntityException e) {
            Debug.logError(e, "Error generating PDF: " + e.toString(), module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentPDFGeneratingError", UtilMisc.toMap("errorString", e.toString()), locale));
        } catch (GeneralException e) {
            Debug.logError(e, "Error generating PDF: " + e.toString(), module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentPDFGeneratingError", UtilMisc.toMap("errorString", e.getMessage()), locale));
        } catch (Exception e) {
            Debug.logError(e, "Error generating PDF: " + e.toString(), module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentPDFGeneratingError", UtilMisc.toMap("errorString", e.toString()), locale));
        }

        Map<String, Object> results = ServiceUtil.returnSuccess();
        results.put("surveyResponseId", surveyResponseId);
        return results;
    }

    /**
     */
    public static Map<String, Object> getAcroFieldsFromPdf(DispatchContext dctx, Map<String, ? extends Object> context) {
        Map<String, Object> acroFieldMap = FastMap.newInstance();
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            Delegator delegator = dctx.getDelegator();
            ByteBuffer byteBuffer = getInputByteBuffer(context, delegator);
            PdfReader r = new PdfReader(byteBuffer.array());
            PdfStamper s = new PdfStamper(r,os);
            AcroFields fs = s.getAcroFields();
            Map<String, Object> map = UtilGenerics.checkMap(fs.getFields());
            s.setFormFlattening(true);

            // Debug code to get the values for setting TDP
    //        String[] sa = fs.getAppearanceStates("TDP");
    //        for (int i=0;i<sa.length;i++)
    //            Debug.logInfo("Appearance="+sa[i]);

            for (String fieldName : map.keySet()) {
                String parmValue = fs.getField(fieldName);
                acroFieldMap.put(fieldName, parmValue);
            }

        } catch (DocumentException e) {
            System.err.println(e.getMessage());
            return ServiceUtil.returnError(e.getMessage());
        } catch (GeneralException e) {
            System.err.println(e.getMessage());
            return ServiceUtil.returnError(e.getMessage());
        } catch (IOException ioe) {
            System.err.println(ioe.getMessage());
            return ServiceUtil.returnError(ioe.getMessage());
        }

    Map<String, Object> results = ServiceUtil.returnSuccess();
    results.put("acroFieldMap", acroFieldMap);
    return results;
    }

    /**
     */
    public static Map<String, Object> setAcroFields(DispatchContext dctx, Map<String, ? extends Object> context) {
        Map<String, Object> results = ServiceUtil.returnSuccess();
        Delegator delegator = dctx.getDelegator();
        try {
            Map<String, Object> acroFieldMap = UtilGenerics.checkMap(context.get("acroFieldMap"));
            ByteBuffer byteBuffer = getInputByteBuffer(context, delegator);
            PdfReader r = new PdfReader(byteBuffer.array());
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PdfStamper s = new PdfStamper(r, baos);
            AcroFields fs = s.getAcroFields();
            Map<String, Object> map = UtilGenerics.checkMap(fs.getFields());
            s.setFormFlattening(true);

            // Debug code to get the values for setting TDP
    //      String[] sa = fs.getAppearanceStates("TDP");
    //      for (int i=0;i<sa.length;i++)
    //          Debug.logInfo("Appearance="+sa[i]);

            for (String fieldName : map.keySet()) {
                String fieldValue = fs.getField(fieldName);
                Object obj = acroFieldMap.get(fieldName);
                if (obj instanceof Date) {
                    Date d=(Date)obj;
                    fieldValue=UtilDateTime.toDateString(d);
                } else if (obj instanceof Long) {
                    Long lg=(Long)obj;
                    fieldValue=lg.toString();
                } else if (obj instanceof Integer) {
                    Integer ii=(Integer)obj;
                    fieldValue=ii.toString();
                }   else {
                    fieldValue=(String)obj;
                }

                if (UtilValidate.isNotEmpty(fieldValue)) {
                    fs.setField(fieldName, fieldValue);
                }
            }

            s.close();
            baos.close();
            ByteBuffer outByteBuffer = ByteBuffer.wrap(baos.toByteArray());
            results.put("outByteBuffer", outByteBuffer);
        } catch (DocumentException e) {
            System.err.println(e.getMessage());
            results = ServiceUtil.returnError(e.getMessage());
        } catch (GeneralException e) {
            System.err.println(e.getMessage());
            results = ServiceUtil.returnError(e.getMessage());
        } catch (FileNotFoundException e) {
            System.err.println(e.getMessage());
            results = ServiceUtil.returnError(e.getMessage());
        } catch (IOException ioe) {
            System.err.println(ioe.getMessage());
            results = ServiceUtil.returnError(ioe.getMessage());
        } catch (Exception ioe) {
            System.err.println(ioe.getMessage());
            results = ServiceUtil.returnError(ioe.getMessage());
        }
        return results;
    }


    /**
     */
    public static Map<String, Object> buildPdfFromSurveyResponse(DispatchContext dctx, Map<String, ? extends Object> rcontext) {
        Map<String, Object> context = UtilMisc.makeMapWritable(rcontext);
        Delegator delegator = dctx.getDelegator();
        //LocalDispatcher dispatcher = dctx.getDispatcher();
        Map<String, Object> results = ServiceUtil.returnSuccess();
        String surveyResponseId = (String)context.get("surveyResponseId");
        String contentId = (String)context.get("contentId");
        String surveyId = null;

        Document document = new Document();
        try {
            if (UtilValidate.isNotEmpty(surveyResponseId)) {
                GenericValue surveyResponse = EntityQuery.use(delegator).from("SurveyResponse").where("surveyResponseId", surveyResponseId).queryOne();
                if (surveyResponse != null) {
                    surveyId = surveyResponse.getString("surveyId");
                }
            }
            if (UtilValidate.isNotEmpty(surveyId) && UtilValidate.isEmpty(contentId)) {
                GenericValue survey = EntityQuery.use(delegator).from("Survey").where("surveyId", surveyId).queryOne();
                if (survey != null) {
                    String acroFormContentId = survey.getString("acroFormContentId");
                    if (UtilValidate.isNotEmpty(acroFormContentId)) {
                        context.put("contentId", acroFormContentId);
                    }
                }
            }

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PdfWriter.getInstance(document, baos);

            List<GenericValue> responses = EntityQuery.use(delegator).from("SurveyResponseAnswer").where("surveyResponseId", surveyResponseId).queryList();
            for (GenericValue surveyResponseAnswer : responses) {
                String value = null;
                String surveyQuestionId = (String) surveyResponseAnswer.get("surveyQuestionId");
                GenericValue surveyQuestion = EntityQuery.use(delegator).from("SurveyQuestion").where("surveyQuestionId", surveyQuestionId).queryOne();
                String questionType = surveyQuestion.getString("surveyQuestionTypeId");
                // DEJ20060227 this isn't used, if needed in the future should get from SurveyQuestionAppl.externalFieldRef String fieldName = surveyQuestion.getString("description");
                if ("OPTION".equals(questionType)) {
                    value = surveyResponseAnswer.getString("surveyOptionSeqId");
                } else if ("BOOLEAN".equals(questionType)) {
                    value = surveyResponseAnswer.getString("booleanResponse");
                } else if ("NUMBER_LONG".equals(questionType) || "NUMBER_CURRENCY".equals(questionType) || "NUMBER_FLOAT".equals(questionType)) {
                    Double num = surveyResponseAnswer.getDouble("numericResponse");
                    if (num != null) {
                        value = num.toString();
                    }
                } else if ("SEPERATOR_LINE".equals(questionType) || "SEPERATOR_TEXT".equals(questionType)) {
                    // not really a question; ingore completely
                } else {
                    value = surveyResponseAnswer.getString("textResponse");
                }
                Chunk chunk = new Chunk(surveyQuestion.getString("question") + ": " + value);
                Paragraph p = new Paragraph(chunk);
                document.add(p);
            }
            ByteBuffer outByteBuffer = ByteBuffer.wrap(baos.toByteArray());
            results.put("outByteBuffer", outByteBuffer);
        } catch (GenericEntityException e) {
            System.err.println(e.getMessage());
            results = ServiceUtil.returnError(e.getMessage());
        } catch (DocumentException e) {
            System.err.println(e.getMessage());
            results = ServiceUtil.returnError(e.getMessage());
        }

        return results;
    }

    /**
     * Returns list of maps with "question"->SurveyQuestion and "response"->SurveyResponseAnswer
     */
    public static Map<String, Object> buildSurveyQuestionsAndAnswers(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        //LocalDispatcher dispatcher = dctx.getDispatcher();
        Map<String, Object> results = ServiceUtil.returnSuccess();
        String surveyResponseId = (String)context.get("surveyResponseId");
        List<Object> qAndA = FastList.newInstance();

        try {
            List<GenericValue> responses = EntityQuery.use(delegator).from("SurveyResponseAnswer").where("surveyResponseId", surveyResponseId).queryList();
            for (GenericValue surveyResponseAnswer : responses) {
                String surveyQuestionId = (String) surveyResponseAnswer.get("surveyQuestionId");
                GenericValue surveyQuestion = EntityQuery.use(delegator).from("SurveyQuestion").where("surveyQuestionId", surveyQuestionId).queryOne();
                qAndA.add(UtilMisc.toMap("question", surveyQuestion, "response", surveyResponseAnswer));
            }
            results.put("questionsAndAnswers", qAndA);
        } catch (GenericEntityException e) {
            System.err.println(e.getMessage());
            results = ServiceUtil.returnError(e.getMessage());
        }

        return results;
    }

    /**
     */
    public static Map<String, Object> setAcroFieldsFromSurveyResponse(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Map<String, Object> results = ServiceUtil.returnSuccess();
        Map<String, Object> acroFieldMap = FastMap.newInstance();
        String surveyResponseId = (String)context.get("surveyResponseId");
        String acroFormContentId = null;

        try {
            String surveyId = null;
            if (UtilValidate.isNotEmpty(surveyResponseId)) {
                GenericValue surveyResponse = EntityQuery.use(delegator).from("SurveyResponse").where("surveyResponseId", surveyResponseId).queryOne();
                if (surveyResponse != null) {
                    surveyId = surveyResponse.getString("surveyId");
                }
            }

            if (UtilValidate.isNotEmpty(surveyId)) {
                GenericValue survey = EntityQuery.use(delegator).from("Survey").where("surveyId", surveyId).queryOne();
                if (survey != null) {
                    acroFormContentId = survey.getString("acroFormContentId");
                }
            }

            List<GenericValue> responses = EntityQuery.use(delegator).from("SurveyResponseAnswer").where("surveyResponseId", surveyResponseId).queryList();
            for (GenericValue surveyResponseAnswer : responses) {
                String value = null;
                String surveyQuestionId = (String) surveyResponseAnswer.get("surveyQuestionId");

                GenericValue surveyQuestion = EntityQuery.use(delegator).from("SurveyQuestion").where("surveyQuestionId", surveyQuestionId).cache().queryOne();

                GenericValue surveyQuestionAppl = EntityQuery.use(delegator).from("SurveyQuestionAppl")
                        .where("surveyId", surveyId, 
                                "surveyQuestionId", surveyQuestionId)
                        .orderBy("-fromDate")
                        .filterByDate().cache().queryFirst();

                String questionType = surveyQuestion.getString("surveyQuestionTypeId");
                String fieldName = surveyQuestionAppl.getString("externalFieldRef");
                if ("OPTION".equals(questionType)) {
                    value = surveyResponseAnswer.getString("surveyOptionSeqId");
                } else if ("BOOLEAN".equals(questionType)) {
                    value = surveyResponseAnswer.getString("booleanResponse");
                } else if ("NUMBER_LONG".equals(questionType) || "NUMBER_CURRENCY".equals(questionType) || "NUMBER_FLOAT".equals(questionType)) {
                    Double num = surveyResponseAnswer.getDouble("numericResponse");
                    if (num != null) {
                        value = num.toString();
                    }
                } else if ("SEPERATOR_LINE".equals(questionType) || "SEPERATOR_TEXT".equals(questionType)) {
                    // not really a question; ingore completely
                } else {
                    value = surveyResponseAnswer.getString("textResponse");
                }
                acroFieldMap.put(fieldName, value);
            }
        } catch (GenericEntityException e) {
            System.err.println(e.getMessage());
            return ServiceUtil.returnError(e.getMessage());
        }

        try {
            ModelService modelService = dispatcher.getDispatchContext().getModelService("setAcroFields");
            Map<String, Object> ctx = modelService.makeValid(context, "IN");
            ctx.put("acroFieldMap", acroFieldMap);
            ctx.put("contentId", acroFormContentId);
            Map<String, Object> map = dispatcher.runSync("setAcroFields", ctx);
            if (ServiceUtil.isError(map)) {
                return ServiceUtil.returnError(ServiceUtil.makeErrorMessage(map, null, null, null, null));
            }
            String pdfFileNameOut = (String) context.get("pdfFileNameOut");
            ByteBuffer outByteBuffer = (ByteBuffer) map.get("outByteBuffer");
            results.put("outByteBuffer", outByteBuffer);
            if (UtilValidate.isNotEmpty(pdfFileNameOut)) {
                FileOutputStream fos = new FileOutputStream(pdfFileNameOut);
                fos.write(outByteBuffer.array());
                fos.close();
            }
        } catch (FileNotFoundException e) {
            System.err.println(e.getMessage());
            results = ServiceUtil.returnError(e.getMessage());
        } catch (IOException e) {
            System.err.println(e.getMessage());
            results = ServiceUtil.returnError(e.getMessage());
        } catch (GenericServiceException e) {
            System.err.println(e.getMessage());
            results = ServiceUtil.returnError(e.getMessage());
        }

    return results;
    }

    public static ByteBuffer getInputByteBuffer(Map<String, ? extends Object> context, Delegator delegator) throws GeneralException {
        ByteBuffer inputByteBuffer = (ByteBuffer)context.get("inputByteBuffer");

        if (inputByteBuffer == null) {
            String pdfFileNameIn = (String)context.get("pdfFileNameIn");
            String contentId = (String)context.get("contentId");
            if (UtilValidate.isNotEmpty(pdfFileNameIn)) {
                try {
                    FileInputStream fis = new FileInputStream(pdfFileNameIn);
                    int c;
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    while ((c = fis.read()) != -1) baos.write(c);
                    inputByteBuffer = ByteBuffer.wrap(baos.toByteArray());
                } catch (FileNotFoundException e) {
                    throw(new GeneralException(e.getMessage()));
                } catch (IOException e) {
                    throw(new GeneralException(e.getMessage()));
                }
            } else if (UtilValidate.isNotEmpty(contentId)) {
                try {
                    Locale locale = (Locale)context.get("locale");
                    String https = (String)context.get("https");
                    String webSiteId = (String)context.get("webSiteId");
                    String rootDir = (String)context.get("rootDir");
                    GenericValue content = EntityQuery.use(delegator).from("Content").where("contentId", contentId).cache().queryOne();
                    String dataResourceId = content.getString("dataResourceId");
                    inputByteBuffer = DataResourceWorker.getContentAsByteBuffer(delegator, dataResourceId, https, webSiteId, locale, rootDir);
                } catch (GenericEntityException e) {
                    throw(new GeneralException(e.getMessage()));
                } catch (IOException e) {
                    throw(new GeneralException(e.getMessage()));
                }
            }
        }
        return inputByteBuffer;
    }
}
