/*
 * 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.integrator.security.LogonSession;
import com.queplix.core.modules.config.utils.SysPropertyManager;
import com.queplix.core.modules.eqlext.utils.FileManager;
import com.queplix.core.modules.eqlext.error.FileManagerException;
import com.queplix.core.utils.DateHelper;
import com.queplix.core.utils.StringHelper;
import org.apache.regexp.RE;
import org.apache.regexp.RESyntaxException;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

/**
 * Inbox Helper.
 *
 * @author Konstantin Mironov
 * @since 8 Dec 2006
 */
public class InboxHelper {

    // Generic mail-related constants.
    // ===============================

    /**
     * Mailer property.
     */
    public static final String MAILER_PROPERTY = "DEFAULT_MAILER";

    /**
     * Sender property.
     */
    public static final String SENDER_PROPERTY = "DEFAULT_SENDER";

    /**
     * Mail header to name the mailer software.
     */
    public static final String HEADER_X_MAILER = "X-Mailer";

    /**
     * Mail header for the object-bound messages.
     */
    public static final String HEADER_X_TIKET = "X-Tiket";

    /**
     * Mail header for the encoding.
     */
    public static final String CONTENT_TRANSFER_ENCODING
            = "CONTENT-TRANSFER-ENCODING";
    public static final String CONTENT_TRANSFER_ENCODING_BASE64 = "BASE64";
    public static final String CONTENT_ID_CAPTION = "cid:";
    public static final String CONTENT_TYPE_HTML = "TEXT/HTML";
    public static final String CONTENT_TYPE_PLAIN = "TEXT/PLAIN";
    public static final String CONTENT_TYPE_TEXT = "TEXT";
    public static final String CONTENT_TYPE_MESSAGE = "MESSAGE/RFC822";
    public static final String CONTENT_TYPE_ALTERNATIVE
            = "MULTIPART/ALTERNATIVE";

    /**  */
    public static final String SERVLET_UPLOAD_NAME
            = "../attachmentUpload/getpridf?process_id=";
    public static final String SERVLET_UPLOAD_FILENAME = "&filename=";

    /**
     * Supported account IDs.
     */
    public static final String ACCOUNT_POP3 = "POP3";
    public static final String ACCOUNT_IMAP4 = "IMAP";
    public static final String[] ACCOUNTS = {
            ACCOUNT_POP3,
            ACCOUNT_IMAP4
    };

    public static final int EMAIL_MESSAGE = 0;
    public static final int ALERT_MESSAGE = 1;

    // Deleted state for delete_flag field
    public static final int DELETE_FLAG = 1;

    /**
     * Pattern variable to find image insertion in mail body.
     */
    public static final String IMAGE_PATTERN
            = "<img\\s+src=['\"]([^'\"]+)['\"]\\s+attachedId=['\"]([^'\"]+)['\"]";
    public static final String IMAGE_PATTERN_INCOM
            = "<img\\s+.*[\\r\\n]*src=[\\w]*['\"]([^\">]*)";

    public static final String IMAGE_PATTERN_OUT_EMAIL
            = "<img\\s+.*[\\r\\n]*.*src=\"([^'\"]+)\"";

    public static final String IMAGE_PATTERN_OUT_EMAIL_EXIST
            = "<img\\s+.*[\\r\\n]*src=\"(.*/attachmentUpload/getpridf\\?process_id=([0-9]*).*[\\r\\n]*filename=([^\"]*))\"";

    public static final String IMAGE_PATTERN_UPSERVLET_OUT_EMAIL
            = "<img\\s.*src=['\"](http://.*/fileUpload/get\\?filepath=([^'\"]+))\"";

    public static final String TAG_A_PATTERN = "<a\\s+.*[\\r\\n]*href=\"(.+)\"";
    public static final String TAG_A_TARGET = " target=\"_blank\"";

    public static final String INDICATION_PREFIX_HTML
            = "<center><label style=\"font-family:Arial;font-weight:bold;font-size:10pt\">";
    public static final String[] MONTHS = {
            "Jan",
            "Feb",
            "Mar",
            "Apr",
            "May",
            "Jun",
            "Jul",
            "Aug",
            "Sep",
            "Oct",
            "Nov",
            "Dec"
    };
    public static final String INDICATION_POSTFIX_HTML = "</label></center>";
    public static final String DELIMITER_HTML = "<br>";

    /*
    private static final InboxManagerLocal MANAGER_LOCAL =
            (InboxManagerLocal)new CacheObjectManager().getLocalObject(JNDINames.InboxManager, InboxManagerLocalHome.class);
            */

    // Static mail-related methods.
    // ============================

    //
    // Build URI.
    //

    public static final String toURI(Account account) {
        return toURI(account.getProviderName(),
                account.getServer(),
                account.getPort(),
                account.getFolderName(),
                account.getName());
    }


    public static final String toURI(String proto, String host) {
        return toURI(proto, host, null);
    }

    public static final String toURI(String proto, String host, Integer port) {
        return toURI(proto, host, port, null);
    }

    public static final String toURI(String proto,
                                     String host,
                                     Integer port,
                                     String folderName) {
        return toURI(proto, host, port, folderName, null);
    }

    public static final String toURI(String proto,
                                     String host,
                                     Integer port,
                                     String folderName,
                                     String name) {
        String s = proto + "://";
        if(name != null) {
            s += name + "@";
        }
        s += host;
        if(port != null) {
            s += ":" + port;
        }
        if(folderName != null) {
            s += "/" + folderName;
        }
        return s;
    }

    /**
     * Returns mailer specified in system properties.
     *
     * @return String
     */
    public static String getMailer() {
        return SysPropertyManager.getProperty(MAILER_PROPERTY);
    }

    /**
     * Returns default sender.
     *
     * @return String
     */
    public static String getDefSender() {
        return getDefSender(null);
    }

    /**
     * Returns default sender.
     *
     * @param ls LogonSession
     * @return String
     */
    public static String getDefSender(LogonSession ls) {
        String defaultSender = null;
        if(ls != null) {
            defaultSender = ls.getUser().getEmail();
        }
        if(StringHelper.isEmpty(defaultSender)) {
            defaultSender = SysPropertyManager.getProperty(SENDER_PROPERTY);
        }
        if(StringHelper.isEmpty(defaultSender)) {
            throw new NullPointerException(
                    "No mail default sender specified in property file.");
        }
        return defaultSender;
    }

    /**
     * Checks if <code>fileName</code> attachment is in mail content.
     *
     * @param fileName full attachment name
     * @return boolean
     */
    public static boolean isContentAttachment(String fileName) {
        if(fileName == null) {
            return false;
        } else {
            return fileName.toLowerCase().startsWith(CONTENT_ID_CAPTION);
        }
    }

    /**
     * Returns attachment's 'Content-ID' header value.
     *
     * @param fileName full attachment name
     * @return String
     */
    public static String getContentId(String fileName) {
        if(fileName == null || fileName.length() < CONTENT_ID_CAPTION
                .length()) {
            return null;
        } else {
            if (fileName.startsWith(CONTENT_ID_CAPTION))
                return fileName.substring(CONTENT_ID_CAPTION.length());
            else
                return fileName;
        }
    } // getContentId(String) : String

    /**
     * Retruns normilized attachment name.
     * Retrive file name from <code>fileName</code>.
     * Example:
     * Content-ID: <image001.jpg@01C62295.60D0B580>
     *
     * @param fileName full attachment name
     * @param uniqueID unique ID to generate unique attachment name.
     * @return String
     */
    public static String normalizeAttachmentName(String fileName,
                                                 int uniqueID) {

        if(StringHelper.isEmpty(fileName)) {
            return generateUniqueAttachName(uniqueID);
        }

        if(!isContentAttachment(fileName)) {
            return fileName;
        }

        String contentId = getContentId(fileName);
        RE re;
        try {
            re = new RE("[\\w\\u002E\\u002D\\s\\[\\]']+",
                    RE.MATCH_CASEINDEPENDENT);
        } catch (RESyntaxException rex) {
            throw new GenericSystemException(
                    "Regexp exception: " + rex.getMessage(), rex);
        }
        String name;
        if(re.match(contentId)) {
            name = contentId.substring(re.getParenStart(0), re.getParenEnd(0));
        } else {
            name = contentId;
        }

        /** @todo [alb] test MimeUtility#encodeText with Russian chars
        if( name != null ) {
        // Set encoded file name.
        try {
        name = MimeUtility.encodeText( name );
        } catch( UnsupportedEncodingException ex ) {
        throw new GenericSystemException( "Encoding exception: " + ex.getMessage(), ex );
        }
        }
         */

        return name;
    }

    /**
     * The method returns unique key for a message
     *
     * @param message Inbox Message object
     * @return digest string
     */
    public static String getMessageDigest(InboxMessage message) {
        String msgDigest;
        if(message == null && message.getBody() == null) {
            return StringHelper.EMPTY_VALUE;
        } // if (message == null || message.getBody() == null)

        try {
            MessageDigest digestObject = MessageDigest.getInstance("MD5");
            digestObject.update(message.getBody().getBytes("UTF-8"));
            byte[] digest = digestObject.digest();
            StringBuffer sbNewDigest = new StringBuffer();
            for(int i = 0; i < digest.length; i++) {
                int newByte = digest[i] + 128;
                String nextByte = Integer.toHexString(newByte).toUpperCase();
                if(nextByte.length() == 1) {
                    nextByte = "0" + nextByte;
                } // if (nextByte.length() == 1)
                sbNewDigest.append(nextByte);
            } // for (int i = 0; i < digest.length; i++)
            msgDigest = sbNewDigest.toString();
        } catch (NoSuchAlgorithmException ex) {
            msgDigest = StringHelper.EMPTY_VALUE;
        } catch (Exception ex) {
            msgDigest = StringHelper.EMPTY_VALUE;
        } // try
        return msgDigest;
    } // getMessageDigest(InboxMessage message) : String

    /**
     * Returns new unique name for attachment.
     *
     * @param uniqueID int
     * @return String
     */
    public static String generateUniqueAttachName(int uniqueID) {
        return "Att" + uniqueID;
    }

    public static String getDateAsString() {
        Date currentDate = DateHelper.getNowDate();
        String dateAsString = ", " +
                addLeadingZero(currentDate.getDate()) +
                " " +
                MONTHS[currentDate.getMonth()] +
                " " +
                (currentDate.getYear() + 1900) +
                " " +
                addLeadingZero(currentDate.getHours()) +
                ":" +
                addLeadingZero(currentDate.getMinutes());
        return dateAsString;
    } // getDateAsString() : String

    /**
     * The method gets attachment using path.
     *
     * @return String
     */
    public static FileManager.FileInfo getAttachmentAsFile(String filePath) {
        FileManager.FileInfo fi = null;
        try {
            // Load file.
            fi = FileManager.loadFile(filePath);

        } catch (FileManagerException ex) {
            // DEBUG();
        }
        return fi;
    }


    private static String addLeadingZero(int n) {
        return n > 9 ? Integer.toString(n):"0" + n;
    } // addLeadingZero(int) : String
} // class InboxHelper
