package nl.hsleiden.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.onehippo.cms7.eforms.hst.beans.FormBean;
import com.onehippo.cms7.eforms.hst.model.AbstractField;
import com.onehippo.cms7.eforms.hst.model.Form;

public class ITextPdfForm {

    private static final Logger LOG = LoggerFactory.getLogger(ITextPdfForm.class);
    
    public InputStream createFormPdf(FormBean formBean, Form form, String introText) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        try {
            Document doc = new Document(PageSize.A4, 50, 50, 50, 50);
            PdfWriter.getInstance(doc, baos);

            doc.open();
            
            addTitle(formBean, doc);
            doc.add(Chunk.NEWLINE);

            addIntroduction(formBean, introText, doc);
            doc.add(Chunk.NEWLINE);

            addFormData(form, doc);
            doc.add(Chunk.NEWLINE);

            doc.close();
        } catch (DocumentException e) {
            LOG.error("exception creating pdf out of form data", e);
        }

        return new ByteArrayInputStream(baos.toByteArray());
    }

    private void addFormData(Form form, Document doc) throws DocumentException {
        List<AbstractField> fields = form.getFields();

        PdfPTable tbl = new PdfPTable(2);
        for (AbstractField abstractField : fields) {
            if (abstractField.isMultiple()) {
                addMultivalueFields(tbl, abstractField);
            } else {
                addSingleValueFields(tbl, abstractField);
            }
        }
        doc.add(tbl);
    }

    private void addSingleValueFields(PdfPTable tbl, AbstractField abstractField) {
        if (abstractField != null && abstractField.getValue() != null && !abstractField.getValue().isEmpty()) {
            addTableCell(tbl, abstractField.getName());
            addTableCell(tbl, abstractField.getValue());
        }
    }

    private void addMultivalueFields(PdfPTable tbl, AbstractField abstractField) {
        Map<String, Collection<String>> multiValues = abstractField.getMultiValues();
        for (Entry<String, Collection<String>> multivaluesEntry : multiValues.entrySet()) {
            if (multivaluesEntry.getValue().toString() != null && !multivaluesEntry.getValue().isEmpty()
                    && isRadioValueNotEmpty(abstractField)) {
                addTableCell(tbl, multivaluesEntry.getKey());
                addTableCell(tbl, multivaluesEntry.getValue().toString());
            }
        }
    }

    private boolean isRadioValueNotEmpty(AbstractField abstractField) {
        return "radiogroup".equalsIgnoreCase(abstractField.getType()) && abstractField.getValue() != null
                && !abstractField.getValue().isEmpty();
    }

    private void addTableCell(PdfPTable tbl, String content) {
        PdfPCell cell = new PdfPCell(new Phrase(content));
        cell.disableBorderSide(Rectangle.BOX);
        tbl.addCell(cell);
    }

    private void addIntroduction(FormBean formBean, String introText, Document doc)
            throws DocumentException {
        if (introText != null && !introText.isEmpty()) {
            doc.add(new Paragraph(introText));
        }
    }

    private void addTitle(FormBean formBean, Document doc) throws DocumentException {
        String formName = formBean.getFormName();
        if (formName != null && !formName.isEmpty()) {
            Font font = new Font(FontFamily.HELVETICA, 20, Font.BOLD, BaseColor.BLACK);
            Phrase titlePhrase = new Phrase(formBean.getFormName(), font);
            doc.add(titlePhrase);
            doc.add(Chunk.NEWLINE);
        }
    }
}

@@ -1034,20 +1034,16 @@
 class);%0A
-    
 %0A    pub
@@ -1345,28 +1345,16 @@
 open();%0A
-            
 %0A       
@@ -2096,70 +2096,74 @@
     
-addMultivalueFields(tbl, abstractField);%0A            %7D else %7B%0A
+if (%22radiogroup%22.equalsIgnoreCase(abstractField.getType())) %7B%0A    
     
@@ -2224,35 +2224,36 @@
             
-%7D%0A
     
-    %7D
+%7D else %7B
 %0A        doc
@@ -2253,95 +2253,44 @@
     
-doc.add(tbl);%0A
+  
     
-%7D%0A%0A
     
-private void addSingleValueFields(PdfPTable tbl, AbstractField
+  addMultivalueFields(tbl,
  abs
@@ -2292,34 +2292,33 @@
 , abstractField)
- %7B
+;
 %0A        if (abs
@@ -2314,136 +2314,75 @@
     
-if (abstractField != null && abstractField.getValue() != null && !abstractField.getValue().isEmpty()) %7B%0A            addTableCell
+        %7D%0A            %7D else %7B%0A                addSingleValueFields
 (tbl
@@ -2400,18 +2400,8 @@
 ield
-.getName()
 );%0A 
@@ -2415,62 +2415,41 @@
     
-addTableCell(tbl, abstractField.getValue());%0A        %7D
+%7D%0A        %7D%0A        doc.add(tbl);
 %0A   
@@ -2845,42 +2845,56 @@
  && 
-isRadioValueNotEmpty(abstractField
+!multivaluesEntry.getValue().toString().isEmpty(
 )) %7B
@@ -3078,37 +3078,49 @@
 ate 
-boolean isRadioValueNotEmpty(
+void addSingleValueFields(PdfPTable tbl, 
 Abst
@@ -3158,45 +3158,37 @@
     
-return %22radiogroup%22.equalsIgnoreCase(
+if (abstractField != null && 
 abst
@@ -3204,19 +3204,28 @@
 .get
-Type())
+Value() != null
  && 
+!
 abst
@@ -3248,37 +3248,108 @@
 ue()
- != null%0A                && !
+.isEmpty()) %7B%0A            addTableCell(tbl, abstractField.getName());%0A            addTableCell(tbl, 
 abst
@@ -3372,19 +3372,20 @@
 ue()
-.isEmpty();
+);%0A        %7D
 %0A   
@@ -3674,28 +3674,16 @@
 ent doc)
-%0A           
  throws 

fix for radio buttons handling