/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */

package com.queplix.core.modules.inbox;

import com.queplix.core.error.GenericSystemException;
import com.queplix.core.modules.jeo.gen.InboxObject;
import com.queplix.core.modules.mail.Attachment;
import com.queplix.core.modules.mail.MailAddress;
import com.queplix.core.modules.mail.MailMessage;
import com.queplix.core.utils.async.ASyncRequest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>Inbox Mail data value object.</p>
 *
 * @author Baranov Andrey [ALB]
 * @version $Revision: 1.5 $ $Date: 2006/05/19 19:01:02 $
 */

public class InboxMessage
        extends MailMessage implements ASyncRequest {

    /**
     * Inbox account Id.
     */
    private Long accountId;

    /**
     * List of attachments.
     */
    private List attachments;

    /**
     * Is attachments saved.
     */
    private boolean isAttachmentSaved;

    /**
     * Is attachments saved.
     */
    private HashMap attachmentIDsList;

    /**
     * Total attachment size.
     */
    private long size = 0;

    /**
     * Map of headers. Used only for incoming messages.
     */
    private Map headers;

    /**
     * True - means <code>this</code> was sent from QueWeb sowtware
     */
    private boolean isQuewebMailer;

    /**
     * Message sending timestamp.
     */
    private Date sentTime;

    /**
     * Message receiving timestamp.
     */
    private Date receiveTime;

    /**
     * Generated Message ID for database.
     */
    private String messageUid;

    /**
     * Unique string for the message.
     */
    private String messageDigest;

    /**
     * Generated Message ID for database.
     */
    private Long messageId;

    /**
     * Shows that <code>this</code> updated with parent's <code>parentId</code> data.
     */
    private boolean isParentUpdated = false;

    /**
     * Rejected filter Id
     */
    private Long filterId;

    /**
     * Used forward Id
     */
    private Long routingRuleId;

    /**
     * Used auto reply Id
     */
    private Long autoreplyId;

    /**
     * Used auto reply Id
     */
    private boolean isNewObject = true;

    /**
     * Routing info.
     */
    /**  */
    private Long sender;

    /**  */
    private int senderType;

    /**  */
    private Long workgroupId;

    /**  */
    private Long resipient;

    /**  */
    private Long objectId;

    /**  */
    private Integer objectType;

    /**
     * Message or Alert
     */
    private Integer messageType;

    /**
     * Message or Alert
     */
    private Integer messageObjectType;

    /**
     * Message or Alert
     */
    private Long senderID;

    // --------------------------------------------------------------- Constructors

    //
    // Constructor-copy.
    //

    public InboxMessage(InboxObject obj) {
        this((obj.getEmail_to() == null) ? null:MailAddress.parse(
                obj.getEmail_to()),
                (obj.getMessage_sender_email() == null) ? null
                        :MailAddress.parse(obj.getMessage_sender_email())[0],
                obj.getSubject(),
                (obj.getMessage() == null) ? null:String.valueOf(
                        obj.getMessage()));

        this.accountId = obj.getAccount_id();
        setMessageId(obj.getPkey());
        setCc((obj.getEmail_cc() == null) ? null:MailAddress.parse(
                obj.getEmail_cc()));
        setProcessId(obj.getProcess_id());
        setSentTime(obj.getSent_date());
        setReceiveTime(obj.getReceived_date());
        setRoutingInfo(obj.getRecipient_id(), obj.getWorkgroup_id());
        setObjectInfo(obj.getObject_id(), obj.getObject_type());
    }

    //email message
    public InboxMessage(
            MailAddress[] to,
            MailAddress from,
            String subject,
            String body
    ) {
        super(to, subject, body);
        setFrom(from);
        this.attachments = new ArrayList();
        this.headers = new HashMap();
    } // InboxMessage(MailAddress[], MailAddress, String, String)

    // Alert type message
    public InboxMessage(
            Long messageSender,
            Long recipientId,
            Long workgroupId,
            String subject,
            String body,
            Integer objectType,
            Long objectId
    ) {
        super();
        this.sender = messageSender;
        this.resipient = recipientId;
        this.workgroupId = workgroupId;
        setSubject(subject);
        setBody(body);
        setObjectInfo(objectId, objectType);
    }

    // --------------------------------------------------------------- Getters/Setters

    public Long getAccountId() {
        return accountId;
    }

    public void setAccountId(Long accountId) {
        this.accountId = accountId;
    }

    public Date getSentTime() {
        return sentTime;
    }

    public void setSentTime(Date sentTime) {
        this.sentTime = sentTime;
    }

    public Date getReceiveTime() {
        return receiveTime;
    }

    public void setReceiveTime(Date receiveTime) {
        this.receiveTime = receiveTime;
    }

    public String getMessageUid() {
        return messageUid;
    }

    public void setMessageUid(String messageUid) {
        this.messageUid = messageUid;
    }

    public String getMessageDigest() {
        return messageDigest;
    }

    public void setMessageDigest(String messageDigest) {
        this.messageDigest = messageDigest;
    }

    public Long getMessageId() {
        return messageId;
    }

    public void setMessageId(Long messageId) {
        this.messageId = messageId;
    }

    public Long getFilterId() {
        return filterId;
    }

    public void setFilterId(Long filterId) {
        this.filterId = filterId;
    }

    public Long getRoutingRuleId() {
        return routingRuleId;
    }

    public void setRoutingRuleId(Long routingRuleId) {
        this.routingRuleId = routingRuleId;
    }

    public Long getAutoreplyId() {
        return autoreplyId;
    }

    public void setAutoreplyId(Long autoreplyId) {
        this.autoreplyId = autoreplyId;
    }

    public Long getSender() {
        return sender;
    }

    public void setSender(Long sender) {
        this.sender = sender;
    }

    public int getSenderType() {
        return senderType;
    }

    public void setSenderType(int senderType) {
        this.senderType = senderType;
    }

    public Long getResipient() {
        return resipient;
    }

    public void setResipient(Long resipient) {
        this.resipient = resipient;
    }

    public Long getObjectId() {
        return objectId;
    }

    public Integer getObjectType() {
        return objectType;
    }

    public void setObjectInfo(Long objectId, Integer objectType) {
        this.objectId = objectId;
        this.objectType = objectType;
    }

    public void setSenderID(Long senderID) {
        this.senderID = senderID;
    }

    public Long getSenderID() {
        return this.senderID;
    }

    public Integer getMessageType() {
        return messageType;
    }

    public void setMessageType(Integer messageType) {
        this.messageType = messageType;
    }

    public Integer getMessageObjectType() {
        return messageObjectType;
    }

    public void setMessageObjectType(Integer messageObjectType) {
        this.messageObjectType = messageObjectType;
    }

    public void setRoutingInfo(Long resipient, Long workgroupId) {
        this.resipient = resipient;
        this.workgroupId = workgroupId;
    }

    public Long getWorkgroupId() {
        return workgroupId;
    }

    public void setIsNewObject(boolean isNewObject) {
        this.isNewObject = isNewObject;
    }

    public boolean isNewObject() {
        return isNewObject;
    }

    public List getAttachments() {
        // @see #resetAttachmentList()
        if(attachments.isEmpty() && getProcessId() != null) {
            // [alb] Use AttachmentManagerLocal to load attachments...
            throw new IllegalStateException(
                    "Process ID set but attachment list not initialized. " +
                            "Use AttachmentManager#getTempAttachments(LogonSession,long)");
        } // if (attachments.isEmpty() && getProcessId() != null)
        return attachments;
    } // getAttachments() : List


    public boolean isEmptyAttachmentsList() {
        return attachments.isEmpty();
    }


    public boolean isAttachmentSaved() {
        return isAttachmentSaved;
    }

    public void setIsAttachmentSaved(boolean isAttachmentSaved) {
        this.isAttachmentSaved = isAttachmentSaved;
    }

    public HashMap getAttachmentIDsList() {
        return attachmentIDsList;
    }

    public void setAttachmentIDsList(HashMap attachmentIDsList) {
        this.attachmentIDsList = attachmentIDsList;
    }

    public void addAttachments(Attachment attach) {
        // Sum up attachment size.
        try {
            byte[] data = attach.getData();
            if(data != null) {
                size += data.length;
            }
        } catch (IOException ex) {
            throw new GenericSystemException(ex);
        }
        // Add to the list.
        attachments.add(attach);
    }

    public long getSize() {
        return size;
    }

    public Map getAllHeaders() {
        return Collections.unmodifiableMap(headers);
    }

    public String[] getHeader(String name) {
        List l = (List) headers.get(name);
        if(l == null || l.isEmpty()) {
            return null;
        }
        return (String[]) l.toArray(new String[0]);
    }

    public void addHeader(String name, String value) {
        List l = (List) headers.get(name);
        if(l == null) {
            l = new ArrayList();
            headers.put(name, l);
        }
        l.add(value);
    }

    // --------------------------------------------------------------- Public methods

    /**
     * Returns true if current message was sent from any QueWeb app.
     *
     * @return boolean
     */
    public boolean isQuewebMailer() {
        return isQuewebMailer;
    }

    /**
     * Sets <code>isQuewebMailer</code> to true.
     */
    public void quewebMailer() {
        isQuewebMailer = true;
    }

    /**
     * Returns true if current message was updated with parent information.
     *
     * @return boolean
     */
    public boolean isParentUpdated() {
        return isParentUpdated;
    }

    /**
     * Sets <code>isParentUpdated</code> to true.
     */
    public void parentUpdated() {
        isParentUpdated = true;
    }

    /**
     * Special method: reset attachment list but
     * doesn't change <code>processId</code>.
     */
    public void resetAttachmentList() {
        // @see #getAttachments()
        attachments.clear();
    }

    /*
     * No javadoc
     * @see Object#toString
     */
    public String toString() {
        return "account Id=" + accountId +
                "; message Uid=" + messageUid +
                "; message Id=" + messageId +
                "; from=" + getFrom() +
                "; subject=" + getSubject() +
                "; sent Time=" + sentTime +
                "; receive Time=" + receiveTime +
                "; size=" + size;
    }
}
