package com.capgemini.reports.definition.r07report.printing;

import com.capgemini.framework.common.ResourceHelper;
import com.capgemini.reports.exceptions.FileLoadingException;
import com.capgemini.reports.exceptions.InvalidInputException;
import com.capgemini.reports.templates.CellFormat;
import com.capgemini.reports.templates.Column;
import com.capgemini.reports.templates.DynamicGridTemplateBuilder;

import java.util.List;
import java.util.Map;

/**
 * Create a dynamic template for the report 07.
 */
public class DynamicGridTemplateR07 extends DynamicGridTemplateBuilder {
    private static final int CENTENT_HEIGHT_PX = 13;
    private static final int TITLE_HEIGHT_PX = 45;
    private static final String BLACK = "#000000\"";
    private static final String FORECOLOR = " forecolor=\"";
    private static final String BACKCOLOR_WHITE = " backcolor = \"#FFFFFF\" ";
    private static final String BACKCOLOR_YELLOW = " backcolor = \"#FFFF00\" ";
    private static final String EMPTY_STRING = "";
    private static final String COULEUR_CONFIGURATION_2 = "#FF0000";
    private static final String COULEUR_CONFIGURATION_1 = "#0000FF";
    private static final String TITLE_FIRST_CONFIGURATION = "TITLE_FIRST_CONFIGURATION";
    private static final String TITLE_SECOND_CONFIGURATION = "TITLE_SECOND_CONFIGURATION";
    private final List<String> find;
    private final String config;
    private final List<Integer> sizeColumn;
    private final Map<String, String> mapStyle;
    private final String nameSheet;

    /**
     * Builds a template for the R07 report.
     *
     * @param widths              the column widths
     * @param contentKeys         the KEYs to the cell's content
     * @param formats             the cell formats
     * @param stretchWithOverFlow stretch with overflow?
     * @param findDifference      a list of differences found
     * @param configNum           the number iterated through the conf
     * @param aMapStyle           a Style map
     * @param nameSheetTemplate   a spreadsheet template name
     * @throws FileLoadingException  if unable to load template file
     * @throws InvalidInputException if inputs are incorrect (non-matching List sizes)
     */
    public DynamicGridTemplateR07(final List<Integer> widths, final List<String> contentKeys, final List<CellFormat> formats,
                                  final List<Boolean> stretchWithOverFlow, final List<String> findDifference, final String configNum,
                                  final Map<String, String> aMapStyle, final String nameSheetTemplate) throws FileLoadingException, InvalidInputException {
        super(widths, contentKeys, formats, stretchWithOverFlow, CENTENT_HEIGHT_PX);
        this.sizeColumn = widths;
        this.find = findDifference;
        this.config = configNum;
        this.mapStyle = aMapStyle;
        this.heigthTitle = TITLE_HEIGHT_PX;
        this.listElementTitle.add(TITLE_FIRST_CONFIGURATION);
        this.listElementTitle.add(TITLE_SECOND_CONFIGURATION);
        this.nameSheet = nameSheetTemplate;
        this.setTemplateContent(ResourceHelper.getResourceContent("/Jasper/template/template_R07.jrxml"));
    }

    private StringBuilder getFieldOption() {
        StringBuilder stringBuilder = new StringBuilder(200);
        for (String aFind : find) {
            stringBuilder.append("\n    <field name =\"").append(aFind).append("\" class = \"java.lang.Boolean\"/>");
        }
        stringBuilder.append("\n    <field name =\"").append(config).append("\" class = \"java.lang.Boolean\"/>");
        return stringBuilder;
    }

    @Override
    public String generateCode() {
        defineColumnStyle();
        makeAligment();
        nameSheetDeclaration = nameSheet;
        propertyDeclaration = makePropertyDeclaration();
        fieldsDeclaration = getFieldOption();
        contentStyle = makeStyle(this.columns);
        parametersDeclaration = makeParamTitle();
        titleDeclaration = makeTitle();

        super.setTagValue(TITLE, titleDeclaration.toString());
        super.setTagValue(TITLE_HEIGHT, String.valueOf(heigthTitle));
        super.setTagValue(NAME_SHEET, nameSheetDeclaration);
        super.setTagValue(PROPERTY, propertyDeclaration.toString());
        super.setTagValue(STYLE, contentStyle.toString());
        return super.generateCode();
    }

    private StringBuilder makePropertyDeclaration() {
        return new StringBuilder("\n<property name =\"net.sf.jasperreports.print.keep.full.text\" value=\"true\"/>");
    }

    private StringBuilder makeParamTitle() {
        StringBuilder stringBuilder = new StringBuilder();
        for (String aListElementTitle : listElementTitle) {
            stringBuilder.append(BEGIN_PARAM).append(aListElementTitle).append(END_PARAM);

        }
        return stringBuilder;
    }

    private StringBuilder makeTitle() {
        StringBuilder stringBuilder = new StringBuilder();
        int sizeTitle = 0;
        int yPos = 0;
        int xPos = 0;
        int size = 0;
        for (int i = 0; i < 4; i++) {
            sizeTitle += sizeColumn.get(i);
        }
        for (String aListElementTitle : listElementTitle) {
            stringBuilder.append("<textField>\n <reportElement x=\"0\" y=\"").append(yPos).append("\" width=\"").append(sizeTitle)
                    .append("\" height=\"15\"/>\n<textFieldExpression>").append(BEGIN_VARIABLE_PARAM_DATA).append(aListElementTitle)
                    .append("}]]>\n</textFieldExpression> \n</textField>");
            xPos = sizeTitle;
            for (int i = 4; i < sizeColumn.size(); i++) {
                stringBuilder.append("<textField>\n <reportElement x=\"").append(xPos).append("\" y=\"").append(yPos).append("\" width=\"")
                        .append(sizeColumn.get(i)).append("\" height=\"15\"/> \n<textFieldExpression>\"").append(EMPTY_STRING)
                        .append("\"</textFieldExpression>\n</textField>");
                xPos += sizeColumn.get(i);
            }
            yPos += 15;
        }
        for (Integer aSizeColumn : sizeColumn) {
            stringBuilder.append("<textField> \n<reportElement x=\"").append(size).append("\" y=\"30\" width=\"").append(aSizeColumn)
                    .append("\" height=\"15\"/> \n<textFieldExpression>\"").append(EMPTY_STRING).append("\"</textFieldExpression>\n</textField>");
            size += aSizeColumn;
        }
        return stringBuilder;
    }

    private StringBuilder makeStyle(final List<Column> column) {
        StringBuilder stringBuilder = new StringBuilder();
        boolean findStyleStatic = false;
        int staticStyleFind = 0;
        for (int i = 0; i < column.size(); i++) {
            if ("style_static".equals(column.get(i).getField().getNameStyle())) {
                staticStyleFind++;
                if (!findStyleStatic) {
                    stringBuilder.append(BEGIN_STYLE).append(column.get(i).getField().getNameStyle()).append('\"').append(END_STYLE).append('\n')
                            .append(BEGIN_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_EXPRESSION).append(BEGIN_VARIABLE_DATA_FALSE_BOOLEAN)
                            .append(find.get(find.size() - 1)).append('}').append(MULTIPLE_CONDITIONAL_INCLUSIF)
                            .append(BEGIN_VARIABLE_FUNCTION_FALSE_BOOLEAN).append(config).append("}]]>").append(END_CONDITIONAL_EXPRESSION)
                            .append(BEGIN_STYLE_MODE).append("\"Opaque\"").append(BACKCOLOR_WHITE).append(FORECOLOR + COULEUR_CONFIGURATION_2 + '\"')
                            .append(END_STYLE).append(BEGIN_BOX).append(TOP_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK)
                            .append(END).append(LEFT_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END)
                            .append(BOTTOM_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(RIGHT_PEN)
                            .append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(END_BOX).append(END_STYLE_MODE)
                            .append(END_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_EXPRESSION)
                            .append(BEGIN_VARIABLE_DATA_FALSE_BOOLEAN).append(find.get(find.size() - 1)).append('}')
                            .append(MULTIPLE_CONDITIONAL_INCLUSIF).append(BEGIN_VARIABLE_FUNCTION).append(config).append("}]]>")
                            .append(END_CONDITIONAL_EXPRESSION).append(BEGIN_STYLE_MODE).append("\"Opaque\"").append(BACKCOLOR_WHITE)
                            .append(FORECOLOR + COULEUR_CONFIGURATION_1 + "\"").append(END_STYLE).append(BEGIN_BOX).append(TOP_PEN).append(LINE_WIDTH)
                            .append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(LEFT_PEN).append(LINE_WIDTH).append("0.5\"")
                            .append(LINE_COLOR).append(BLACK).append(END).append(BOTTOM_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR)
                            .append(BLACK).append(END).append(RIGHT_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK)
                            .append(END).append(END_BOX).append(END_STYLE_MODE).append(END_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_STYLE)
                            .append(BEGIN_CONDITIONAL_EXPRESSION).append(BEGIN_VARIABLE_DATA).append(find.get(find.size() - 1)).append('}')
                            .append(MULTIPLE_CONDITIONAL_INCLUSIF).append(BEGIN_VARIABLE_FUNCTION_FALSE_BOOLEAN).append(config).append("}]]>")
                            .append(END_CONDITIONAL_EXPRESSION).append(BEGIN_STYLE_MODE).append("\"Opaque\"").append(BACKCOLOR_YELLOW)
                            .append(FORECOLOR + COULEUR_CONFIGURATION_2 + "\"").append(END_STYLE).append(BEGIN_BOX).append(TOP_PEN).append(LINE_WIDTH)
                            .append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(LEFT_PEN).append(LINE_WIDTH).append("0.5\"")
                            .append(LINE_COLOR).append(BLACK).append(END).append(BOTTOM_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR)
                            .append(BLACK).append(END).append(RIGHT_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK)
                            .append(END).append(END_BOX).append(END_STYLE_MODE).append(END_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_STYLE)
                            .append(BEGIN_CONDITIONAL_EXPRESSION).append(BEGIN_VARIABLE_DATA).append(find.get(find.size() - 1)).append('}')
                            .append(MULTIPLE_CONDITIONAL_INCLUSIF).append(BEGIN_VARIABLE_FUNCTION).append(config).append("}]]>")
                            .append(END_CONDITIONAL_EXPRESSION).append(BEGIN_STYLE_MODE).append("\"Opaque\"").append(BACKCOLOR_YELLOW)
                            .append(FORECOLOR).append(COULEUR_CONFIGURATION_1).append('\"').append(END_STYLE).append(BEGIN_BOX).append(TOP_PEN)
                            .append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(LEFT_PEN).append(LINE_WIDTH)
                            .append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(BOTTOM_PEN).append(LINE_WIDTH).append("0.5\"")
                            .append(LINE_COLOR).append(BLACK).append(END).append(RIGHT_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR)
                            .append(BLACK).append(END).append(END_BOX).append(END_STYLE_MODE).append(END_CONDITIONAL_STYLE).append(END_STYLE_FIRST);
                    findStyleStatic = true;
                }
            } else {
                stringBuilder.append(BEGIN_STYLE).append(column.get(i).getField().getNameStyle()).append('\"').append(END_STYLE).append('\n')
                        .append(BEGIN_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_EXPRESSION).append(BEGIN_VARIABLE_DATA_FALSE_BOOLEAN_CONDITION)
                        .append(find.get(find.size() - 1)).append('}').append(MULTIPLE_CONDITIONAL_INCLUSIF)
                        .append(BEGIN_VARIABLE_FUNCTION_FALSE_BOOLEAN).append(find.get(i - staticStyleFind)).append("}) ")
                        .append(MULTIPLE_CONDITIONAL_INCLUSIF).append(BEGIN_VARIABLE_FUNCTION_FALSE_BOOLEAN).append(config).append("}]]>")
                        .append(END_CONDITIONAL_EXPRESSION).append(BEGIN_STYLE_MODE).append("\"Opaque\"").append(BACKCOLOR_WHITE)
                        .append(FORECOLOR + COULEUR_CONFIGURATION_2 + "\"").append(END_STYLE).append(BEGIN_BOX).append(TOP_PEN).append(LINE_WIDTH)
                        .append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(LEFT_PEN).append(LINE_WIDTH).append("0.5\"")
                        .append(LINE_COLOR).append(BLACK).append(END).append(BOTTOM_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR)
                        .append(BLACK).append(END).append(RIGHT_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END)
                        .append(END_BOX).append(END_STYLE_MODE).append(END_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_STYLE)
                        .append(BEGIN_CONDITIONAL_EXPRESSION).append(BEGIN_VARIABLE_DATA_FALSE_BOOLEAN_CONDITION).append(find.get(find.size() - 1))
                        .append('}').append(MULTIPLE_CONDITIONAL_INCLUSIF).append(BEGIN_VARIABLE_FUNCTION_FALSE_BOOLEAN)
                        .append(find.get(i - staticStyleFind)).append("}) ").append(MULTIPLE_CONDITIONAL_INCLUSIF).append(BEGIN_VARIABLE_FUNCTION)
                        .append(config).append("}]]>").append(END_CONDITIONAL_EXPRESSION).append(BEGIN_STYLE_MODE).append("\"Opaque\"")
                        .append(BACKCOLOR_WHITE).append(FORECOLOR + COULEUR_CONFIGURATION_1 + '\"').append(END_STYLE).append(BEGIN_BOX)
                        .append(TOP_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(LEFT_PEN)
                        .append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(BOTTOM_PEN).append(LINE_WIDTH)
                        .append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(RIGHT_PEN).append(LINE_WIDTH).append("0.5\"")
                        .append(LINE_COLOR).append(BLACK).append(END).append(END_BOX).append(END_STYLE_MODE).append(END_CONDITIONAL_STYLE)
                        .append(BEGIN_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_EXPRESSION).append(BEGIN_VARIABLE_DATA_CONDITION)
                        .append(find.get(find.size() - 1)).append('}').append(MULTIPLE_CONDITIONAL_EXCLUSIF).append(BEGIN_VARIABLE_FUNCTION)
                        .append(find.get(i - staticStyleFind)).append("}) ").append(MULTIPLE_CONDITIONAL_INCLUSIF)
                        .append(BEGIN_VARIABLE_FUNCTION_FALSE_BOOLEAN).append(config).append("}]]>").append(END_CONDITIONAL_EXPRESSION)
                        .append(BEGIN_STYLE_MODE).append("\"Opaque\"").append(BACKCOLOR_YELLOW).append(FORECOLOR + COULEUR_CONFIGURATION_2 + '\"')
                        .append(END_STYLE).append(BEGIN_BOX).append(TOP_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK)
                        .append(END).append(LEFT_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END)
                        .append(BOTTOM_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(RIGHT_PEN)
                        .append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(END_BOX).append(END_STYLE_MODE)
                        .append(END_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_STYLE).append(BEGIN_CONDITIONAL_EXPRESSION)
                        .append(BEGIN_VARIABLE_DATA_CONDITION).append(find.get(find.size() - 1)).append('}').append(MULTIPLE_CONDITIONAL_EXCLUSIF)
                        .append(BEGIN_VARIABLE_FUNCTION).append(find.get(i - staticStyleFind)).append("}) ").append(MULTIPLE_CONDITIONAL_INCLUSIF)
                        .append(BEGIN_VARIABLE_FUNCTION).append(config).append("}]]>").append(END_CONDITIONAL_EXPRESSION).append(BEGIN_STYLE_MODE)
                        .append("\"Opaque\"").append(BACKCOLOR_YELLOW).append(FORECOLOR + COULEUR_CONFIGURATION_1 + '\"').append(END_STYLE)
                        .append(BEGIN_BOX).append(TOP_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END)
                        .append(LEFT_PEN).append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(BOTTOM_PEN)
                        .append(LINE_WIDTH).append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(RIGHT_PEN).append(LINE_WIDTH)
                        .append("0.5\"").append(LINE_COLOR).append(BLACK).append(END).append(END_BOX).append(END_STYLE_MODE)
                        .append(END_CONDITIONAL_STYLE).append(END_STYLE_FIRST);
            }
        }

        return stringBuilder;

    }

    private void makeAligment() {
        for (Column column : this.columns) {
            column.getHeaders().get(0).getFormat().setAlignment("Middle\"");
        }
    }

    /**
     * Allow to associate a style with a column : every column has his own style(except effectivity , revision , CR and CN).
     */
    private void defineColumnStyle() {
        for (Column column : this.columns) {
            if (mapStyle.containsKey(column.getField().getContent())) {
                column.getField().setNameStyle(mapStyle.get(column.getField().getContent()));
            } else {
                column.getField().setNameStyle(null);
            }
            for (int i = 0; i < column.getHeaders().size(); i++) {
                if (mapStyle.containsKey(column.getHeaders().get(i).getContent())) {
                    column.getHeaders().get(i).setNameStyle(mapStyle.get(column.getHeaders().get(i).getContent()));
                } else {
                    column.getHeaders().get(i).setNameStyle(null);
                }
            }
        }
    }
}
