package com.alexanderlogistics;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.imixs.workflow.ItemCollection;

/**
 * Hilfsmethoden für die Berechnung und Validierung von Ein und
 * Ausgangsrechnugnen
 * 
 * - Rundungs Methode
 * - Berechnung der Positionsnummern
 * - Explode Childitems
 * 
 * See:
 * https://stackoverflow.com/questions/2808535/round-a-double-to-2-decimal-places
 * 
 * @author rsoika
 *
 */
public class InvoiceUtil {

    public static final String CHILD_ITEM_PROPERTY = "_ChildItems";
    public static final String ITEM_INVOICE_PERIOD = "invoice.period";
    public static final String ITEM_INVOICE_POSITIONS = "invoice.positions";
    public static final String ITEM_CDTR_NUMBER = "cdtr.number";
    public static final String ITEM_CDTR_NAME = "cdtr.name";
    public static final String ITEM_CDTR_NAME_CARGOSOFT = "cdtr.name.cargosoft";

    public static double round(double value) {
        BigDecimal bd = BigDecimal.valueOf(value);
        bd = bd.setScale(2, RoundingMode.HALF_UP);
        return bd.doubleValue();
    }

    /**
     * Hilfsmethode zum validieren der Mailadresse
     * 
     * @param emailAddress
     * @return
     */
    public static boolean validateEmail(String emailAddress) {
        // String regexPattern = "^(.+)@(\\S+)$";

        String regexPattern = "^(?=.{1,64}@)[A-Za-z0-9_-]+(\\.[A-Za-z0-9_-]+)*@"
                + "[^-][A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,})$";
        return Pattern.compile(regexPattern)
                .matcher(emailAddress)
                .matches();
    }

    @Deprecated
    public static double roundConservative(double value) {
        value = value * 100;
        long tmp = Math.round(value);
        return (double) tmp / 100;
    }

    /**
     * converts the Map List of a workitem into a List of ItemCollectons
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static List<ItemCollection> explodeChildList(ItemCollection workitem) {
        // convert current list of childItems into ItemCollection elements
        ArrayList<ItemCollection> childItems = new ArrayList<ItemCollection>();

        List<Object> mapOrderItems = workitem.getItemValue(CHILD_ITEM_PROPERTY);
        for (Object mapOderItem : mapOrderItems) {
            if (mapOderItem instanceof Map) {
                ItemCollection itemCol = new ItemCollection((Map) mapOderItem);
                childItems.add(itemCol);
            }
        }
        return childItems;
    }

    /**
     * Convert the List of ItemCollections back into a List of Map elements
     * 
     * @param workitem
     */
    @SuppressWarnings({ "rawtypes" })
    public static void implodeChildList(ItemCollection workitem, List<ItemCollection> childItems) {
        List<Map> mapOrderItems = new ArrayList<Map>();
        // convert the child ItemCollection elements into a List of Map
        if (childItems != null) {
            // iterate over all order items..
            for (ItemCollection orderItem : childItems) {
                mapOrderItems.add(orderItem.getAllItems());
            }
            workitem.replaceItemValue(CHILD_ITEM_PROPERTY, mapOrderItems);
        }
    }

    /**
     * Diese Methode berechnet das feld 'invoice.positions' welches eine Valueliste
     * mit allen Positionsnummern aus dem Childliste enthält.
     * Es wird sowohl für Ausgangs wie Eingangsrechnungen genutzt.
     * Das feld wird indiziert, so dass eine gezielte Suche nach positiosnummern
     * möglich ist.
     * 
     * @param workitem
     */
    public static void updateInvoicePositions(ItemCollection workitem) {

        List<String> posList = new ArrayList<String>();
        List<ItemCollection> childs = InvoiceUtil.explodeChildList(workitem);
        for (ItemCollection posItem : childs) {
            String posName = "";
            // Ausgangsrechnung - item=datev.text
            // Eingangsrechnugn - item=name
            if (posItem.hasItem("datev.text")) {
                posName = posItem.getItemValueString("datev.text").trim();
            } else {
                posName = posItem.getItemValueString("name").trim();
            }
            if (!posName.isEmpty()) {
                posList.add(posName);
            }
        }
        // update invoice.positions
        workitem.setItemValue(ITEM_INVOICE_POSITIONS, posList);

    }

}
