/*
 * 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.mail;

import com.queplix.core.integrator.security.User;
import com.queplix.core.integrator.security.WorkGroup;
import com.queplix.core.utils.StringHelper;

import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

/**
 * Mail addresses value object.
 *
 * @author [DAG] Dmitry Gaponenko
 * @author [ALB] Baranov Andrey
 * @author [ONZ] Oleg N. Zhovtanyuk
 */

public class MailAddress
        implements java.io.Serializable {

    // --------------------------------------------------------------- Constants

    /**
     * Mail address delimeter
     */
    public static final String DELIMETETR = ",;";

    // --------------------------------------------------------------- Fields

    /**
     * Sender full name.
     */
    private String fullName = null;

    /**
     * E-mail address.
     */
    private String email = null;

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

    public MailAddress(String fullName, String email) {
        setFullName(fullName);
        setEmail(email);
    }

    public MailAddress(User user) {
        this(user.getFullName(), user.getEmail());
    }

    public MailAddress(WorkGroup group) {
        this(group.getGroupName(), group.getEmail());
    }

    public MailAddress(InternetAddress ia) {
        this(ia.getPersonal(), ia.getAddress());
    }

    public MailAddress(String email) {
        if(email != null) {
            int leftAngle = email.indexOf("<");
            int rightAngle = email.indexOf(">", leftAngle + 1);
            if(leftAngle >= 0 && rightAngle > leftAngle) {
                if(leftAngle - 1 > 0) {
                    setFullName(email.substring(0, leftAngle - 1).trim());
                }
                setEmail(email.substring(leftAngle + 1, rightAngle).trim());
                return;
            }
        }
        setEmail(email);
    }

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

    public String getFullName() {
        return fullName;
    }

    public String getEmail() {
        return email;
    }

    private void setFullName(String fullName) {
        this.fullName = fullName;
    }

    private void setEmail(String email) {
        this.email = email;
    }

    // --------------------------------------------------------------- Static methods

    /**
     * Parse address string. Try to find emails in gicven string separated
     * by <code>DELIMETER</code>.
     *
     * @param s given string
     * @return array of <code>MailAddress</code> objects or NULL.
     */
    public static MailAddress[] parse(String s) {

        if(s == null) {
            throw new NullPointerException("Address is NULL");
        }

        List addrList = new ArrayList();
        StringTokenizer st = new StringTokenizer(s, DELIMETETR);
        while(st.hasMoreTokens()) {
            String email = st.nextToken();
            MailAddress addr = new MailAddress(email);
            addrList.add(addr);
        }

        return (addrList.size() == 0) ? null:
                (MailAddress[]) addrList.toArray(new MailAddress[0]);
    }

    /**
     * Converts the value objects array to string in accordance with RFC 822.
     *
     * @param addresses value object array
     * @return an RFC 822 string
     */
    public static String toRfcString(MailAddress[] addresses) {

        // Checking for null.
        if(addresses == null) {
            return StringHelper.EMPTY_VALUE;
        }

        // Joining...
        StringBuffer sb = new StringBuffer();
        int num = addresses.length;
        for(int i = 0; i < num; i++) {
            if(i > 0) {
                sb.append("; ");
            }
            sb.append(addresses[i].toRfcString());
        }

        // Ok.
        return sb.toString();
    }

    // --------------------------------------------------------------- Helper methods

    /**
     * Converts VO to {@link InternetAddress InternetAddress} object.
     *
     * @return InternetAddress object
     * @throws UnsupportedEncodingException
     * @throws AddressException
     */
    public InternetAddress toInternetAddress()
            throws UnsupportedEncodingException, AddressException {

        if(!isValid()) {
            throw new AddressException("Bad e-mail '" + email + "'");
        }

        if(fullName != null) {
            return new InternetAddress(email, fullName);
        } else {
            return new InternetAddress(email);
        }
    }

    /**
     * Converts value object to string in accordance with RFC 822.
     *
     * @return an RFC 822 string
     */
    public String toRfcString() {
        if(!StringHelper.isEmpty(fullName)) {
            return fullName + " <" + email + ">";
        } else {
            return email;
        }
    }

    /**
     * Check if Mail Address valid or not
     *
     * @return true if valid
     */
    public boolean isValid() {
        return (!StringHelper.isEmpty(email));
    }

    /**
     * Converts VO to string.
     *
     * @return a string like <pre>Name [user@domain]</pre>
     */
    public String toString() {
        return toRfcString();
    }

} // end of class
