package com.fp.log;

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.NoSuchElementException;

import org.apache.log4j.Logger;

import com.fp.base.persistence.util.helper.MessageManager;
import com.fp.common.helper.BeanManager;
import com.fp.dto.Request;
import com.fp.dto.hb.HibernateBean;
import com.fp.persistence.commondb.NestedSave;
import com.fp.persistence.commondb.helper.FormatDates;
import com.fp.persistence.plog.log.TlogHeader;
import com.fp.persistence.plog.log.TlogLoad;
import com.fp.persistence.plog.log.TlogLoadError;
import com.fp.persistence.plog.log.TlogLoadErrorKey;
import com.fp.persistence.plog.log.TlogLoadKey;

// TODO: Auto-generated Javadoc
/**
 * The Class LogBook.
 */
public class LogBook {
    private static final Logger LOG = Logger.getLogger(LogBook.class);

    /** The request. */
    private Request request;

    /** The header. */
    private TlogHeader header;

    /** The process. */
    private HashMap<Long, TlogLoad> process = new HashMap<Long, TlogLoad>();

    /** The process error. */
    private HashMap<Long, Integer> processError = new HashMap<Long, Integer>();

    /** The process count. */
    private long processCount = 0;

    /**
     * Instantiates a new log book.
     * 
     * @param pRequest the request
     * @throws Exception the exception
     */
    public LogBook(Request pRequest) throws Exception {
        this.request = pRequest;
        this.manageHeader();
    }

    /**
     * Manage header.
     * 
     * @throws Exception the exception
     */
    protected void manageHeader() throws Exception {
        this.header = new TlogHeader(this.request.getJournalId(), this.request.getTransactionModule(), this.request.getTransactionCode(),
                this.request.getTransactionVersion());
        this.header.setUsercode(this.request.getUser());
        this.header.setCompanycode(this.request.getCompany());
        this.header.setOfficecode(this.request.getOfficeCode());
        this.header.setBranchcode(this.request.getBranchCode());
        this.header.setRealdate(FormatDates.getInstance().getDataBaseTimestamp());
        this.header.setAccountingdate(BeanManager.convertObject(this.request.get("accountingdate"), Timestamp.class));
        this.header.setAditionaldata(MessageManager.getMessage(this.request));
        this.save(this.header, false);
    }

    /**
     * Save.
     * 
     * @param pBean the bean
     * @throws Exception the exception
     */
    protected void save(HibernateBean pBean, boolean update) throws Exception {
        NestedSave ns = new NestedSave(this.request.getCompany(), update, pBean);
        LogBook.LOG.info(pBean);
        ns.start();
        ns.join();
    }

    /**
     * Adds the process.
     * 
     * @param pData the data
     * @param pId the id
     * @return the long
     * @throws Exception the exception
     */
    public Long addProcess(String pData, String pId) throws Exception {
        long id = ++this.processCount;
        TlogLoadKey lk = new TlogLoadKey(this.request.getJournalId(), id);
        TlogLoad l = new TlogLoad(lk);
        l.setAditionaldata(pData);
        l.setLoadid(pId);
        l.setStatus("P");// P en proceso, E error, S sucessfull
        this.save(l, false);
        this.process.put(id, l);
        return id;
    }

    /**
     * Destroy process.
     * 
     * @param pId the id
     * @throws Exception the exception
     */
    private void destroyProcess(Long pId) throws Exception {
        this.process.remove(pId);
        this.processError.remove(pId);
    }

    /**
     * End process.
     * 
     * @param pId the id
     * @throws Exception the exception
     */
    public void endProcess(Long pId) throws Exception {
        TlogLoad load = this.process.get(pId);
        if (load == null) {
            throw new NoSuchElementException();
        }
        load.setStatus("S");
        this.save(load, true);
        this.destroyProcess(pId);
    }

    public void addDetailError(Long pId, String pData) throws Exception {
        this.addDetailError(pId, pData, null, null);
    }

    /**
     * Adds the detail error.
     * 
     * @param pId the id
     * @param pData the data
     * @param pResultCode the result code
     * @param pIdentifier the identifier
     * @throws Exception the exception
     */
    public void addDetailError(Long pId, String pData, String pResultCode, String pIdentifier) throws Exception {
        Integer errorsequence = this.processError.get(pId);
        errorsequence = (errorsequence == null) ? 0 : errorsequence;
        TlogLoadErrorKey llk = new TlogLoadErrorKey(this.request.getJournalId(), pId, errorsequence);
        this.processError.put(pId, ++errorsequence);
        TlogLoadError ll = new TlogLoadError(llk);
        ll.setMessage(pData);
        ll.setResultcode(pResultCode);
        ll.setIdentifier(pIdentifier);
        this.save(ll, false);
    }

    /**
     * Error process.
     * 
     * @param pId the id
     * @throws Exception the exception
     */
    public void errorProcess(Long pId) throws Exception {
        TlogLoad load = this.process.get(pId);
        if (load == null) {
            throw new NoSuchElementException();
        }
        load.setStatus("E");
        this.save(load, true);
        this.destroyProcess(pId);
    }

    /**
     * The main method.
     * 
     * @param args the arguments
     * @throws Exception the exception
     */
    public static void main(String[] args) throws Exception {
        LogBook l = new LogBook(null);
        Long id = l.addProcess("aSDFGHJ", "ASDFGHJK");
        l.addDetailError(id, "asdfgh", "12", "123");
        l.addDetailError(id, "asdfgh", "12", "123");
        l.addDetailError(id, "asdfgh", "12", "123");
        l.endProcess(id);
        l.errorProcess(id);
    }
}
