/*******************************************************************************
 *  Imixs Workflow Technology
 *  Copyright (C) 2001, 2008 Imixs Software Solutions GmbH,  
 *  http://www.imixs.com
 *  
 *  This program is free software; you can redistribute it and/or 
 *  modify it under the terms of the GNU General Public License 
 *  as published by the Free Software Foundation; either version 2 
 *  of the License, or (at your option) any later version.
 *  
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 *  General Public License for more details.
 *  
 *  You can receive a copy of the GNU General Public
 *  License at http://www.gnu.org/licenses/gpl.html
 *  
 *  Contributors:  
 *  	Imixs Software Solutions GmbH - initial API and implementation
 *  	Ralph Soika
 *******************************************************************************/
package com.alexanderlogistics;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import javax.ejb.EJB;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

import org.imixs.marty.team.TeamService;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.WorkflowKernel;
import org.imixs.workflow.engine.DocumentService;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.engine.scheduler.Scheduler;
import org.imixs.workflow.engine.scheduler.SchedulerException;
import org.imixs.workflow.engine.scheduler.SchedulerService;
import org.imixs.workflow.exceptions.AccessDeniedException;
import org.imixs.workflow.exceptions.ModelException;
import org.imixs.workflow.exceptions.PluginException;
import org.imixs.workflow.exceptions.ProcessingErrorException;
import org.imixs.workflow.exceptions.QueryException;

/**
 * The OPListExportScheduler erzeugt für jeden Berich ein neues Workitem mit
 * einer Excel Datei mit allen offenen Rechnungen.
 * <p>
 * bei den OP Listen für die Abteilungen dürfen nur Rechnungen aktiviert werden,
 * wo die 2. Mahnung bereits versandt wurde bzw. wo die Fälligkeit der
 * Rechnungen 21 Tage übersteigt.
 * <p>
 * The class implements the interface
 * _org.imixs.workflow.engine.scheduler.Scheduler_ and can be used in
 * combination with the Imxis-Workflow Scheduler Service.
 * 
 * @see SchedulerService
 * @author rsoika
 * 
 */
public class OPListExportScheduler implements Scheduler {

    public static final int MAX_COUNT = 999;
    public static final String OPLIST_ERROR = "OPLIST_ERROR";
    public static final int TASK_MAHNUNG_2ND = 5210;
    public static final int TASK_MAHNUNG_LAST = 5220;
    
    public static DateFormat dateFormat = new SimpleDateFormat("ddMMyyyy");
    public static DecimalFormat decimalFormat = new DecimalFormat("0.00",
            new DecimalFormatSymbols(java.util.Locale.GERMANY));

    @EJB
    WorkflowService workflowService;

    @EJB
    DocumentService documentService;

    @EJB
    TeamService teamService;

    private static Logger logger = Logger.getLogger(OPListExportScheduler.class.getName());

    /**
     * This is the method which processes the timeout event depending on the running
     * timer settings.
     * 
     * 
     * 
     * @param timer
     * @throws QueryException
     */
    public ItemCollection run(ItemCollection configuration) throws SchedulerException {
        try {
            configuration.removeItem("_scheduler_logmessage");
            logMessage("....export OP-Listen...", configuration, null);
            // Hole dir alle Bereiche
            List<ItemCollection> spaces = teamService.getSpaces();
            // Jezt erzeugen wir für jeden Bereich ein neues Workitem .
            for (ItemCollection space : spaces) {
                // Gibt es Rechnungen in diesem Space?
                if (existsOverdueInvoices(space)) {
                    // erzeuge eine OP-Liste
                    ItemCollection workitem = new ItemCollection();
                    workitem.setItemValue("space.ref", space.getUniqueID());
                    // set creation date!
                    workitem.setItemValue(WorkflowKernel.CREATED, new Date());
                    processOPListe(workitem);
                } else {
                    logger.info("....no invoices in overdue for "+space.getItemValueString("name"));
                }
            }

            logMessage("...completed", configuration, null);
        } catch (RuntimeException e) {
            // continue with log message
            logger.severe("...OPList  Error");
            logMessage("...Failed to create OPLists: " + e.getMessage(), configuration, null);
        } catch (PluginException | ModelException e2) {
            logger.severe("Error processing OP-List for space: " + e2.getMessage());
            throw new SchedulerException("OP-LIST-ERROR", "OPList Processing failed : " + e2.getMessage(), e2);

        }

        return configuration;
    }

    /**
     * Prüfen ob es Rechnugen in diesem Space gibt die entweder die 2. Mahnstufe
     * erreicht habne oder deren Fälligkeit um mehr als 21 Tage überschritten ist.
     * 
     * @param space
     * @return
     */
    private boolean existsOverdueInvoices(ItemCollection space) {
        List<ItemCollection> invoices = new ArrayList<ItemCollection>();
        try {
            invoices = documentService.find(
                    "$modelversion:rechnungsausgang-de-1.0 AND type:workitem AND $uniqueidref:" + space.getUniqueID(),
                    999, 0);
        } catch (QueryException e) {
            logger.warning("Failed to compute invoice list: " + e.getMessage());
            e.printStackTrace();
        }

        for (ItemCollection invoice : invoices) {
            Date date = invoice.getItemValueDate("invoice.duedate");    
            if (OPListExportAdapter.isOverdue(date,invoice.getTaskID())) {
                return true;
            }
        }
        return false;
    }

    
    
  

    @TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
    public void processOPListe(ItemCollection workitem)
            throws PluginException, AccessDeniedException, ProcessingErrorException, ModelException {
        workflowService.processWorkItem( //
                workitem.task(1000). //
                        event(100). //
                        model("opliste-de-1.0"));

    }

    /**
     * Creates a new log entry stored in the item _scheduler_log. The log can be
     * writen optional to the configuraiton and the workitem
     * 
     * @param message
     * @param configuration
     */
    public void logMessage(String message, ItemCollection configuration, ItemCollection workitem) {
        if (configuration != null) {
            configuration.appendItemValue(Scheduler.ITEM_LOGMESSAGE, message);
        }
        if (workitem != null) {
            workitem.appendItemValue(Scheduler.ITEM_LOGMESSAGE, message);
        }

        logger.info(message);

    }

}
