/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (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.apache.org/licenses/LICENSE-2.0
 *
 * 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 org.apache.commons.vfs2.provider.mime;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.mail.Address;
import javax.mail.Header;
import javax.mail.MessagingException;
import javax.mail.Part;
import javax.mail.internet.MimeMessage;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * A map which tries to allow access to the various aspects of the mail.
 */
public class MimeAttributesMap implements Map<String, Object> {
    private static final String OBJECT_PREFIX = "obj.";

    private final Log log = LogFactory.getLog(MimeAttributesMap.class);
    private final Part part;
    private final Map<String, Method> mimeMessageGetters = new TreeMap<>();

    private Map<String, Object> backingMap;

    public MimeAttributesMap(final Part part) {
        this.part = part;
        addMimeMessageMethod(part.getClass().getMethods());
        addMimeMessageMethod(part.getClass().getDeclaredMethods());
    }

    private void addMimeMessageMethod(final Method[] methods) {
        for (final Method method : methods) {
            if (!Modifier.isPublic(method.getModifiers())) {
                continue;
            }
            if (method.getParameterTypes().length > 0) {
                continue;
            }

            if (method.getName().startsWith("get")) {
                mimeMessageGetters.put(method.getName().substring(3), method);
            } else if (method.getName().startsWith("is")) {
                mimeMessageGetters.put(method.getName().substring(2), method);
            }
        }
    }

    private Map<String, Object> getMap() {
        if (backingMap == null) {
            backingMap = createMap();
        }

        return backingMap;
    }

    private Map<String, Object> createMap() {
        // Object is either a String, or a List of Strings
        final Map<String, Object> ret = new TreeMap<>();

        Enumeration<Header> headers;
        try {
            @SuppressWarnings("unchecked") // Javadoc say Part returns Header
            final Enumeration<Header> allHeaders = part.getAllHeaders();
            headers = allHeaders;
        } catch (final MessagingException e) {
            throw new RuntimeException(e);
        }

        // add all headers
        while (headers.hasMoreElements()) {
            final Header header = headers.nextElement();
            final String headerName = header.getName();

            final Object values = ret.get(headerName);

            if (values == null) {
                ret.put(headerName, header.getValue());
            } else if (values instanceof String) {
                final ArrayList<String> newValues = new ArrayList<>();
                newValues.add((String) values);
                newValues.add(header.getValue());
                ret.put(headerName, newValues);
            } else if (values instanceof List) {
                @SuppressWarnings("unchecked") // we only add Strings to the Lists
                final List<String> list = (List<String>) values;
                list.add(header.getValue());
            }
        }

        // add all simple get/is results (with obj. prefix)
        final Iterator<Entry<String, Method>> iterEntries = mimeMessageGetters.entrySet().iterator();
        while (iterEntries.hasNext()) {
            final Map.Entry<String, Method> entry = iterEntries.next();
            final String name = entry.getKey();
            final Method method = entry.getValue();

            try {
                final Object value = method.invoke(part);
                ret.put(OBJECT_PREFIX + name, value);
            } catch (final IllegalAccessException e) {
                log.debug(e.getLocalizedMessage(), e);
            } catch (final InvocationTargetException e) {
                log.debug(e.getLocalizedMessage(), e);
            }
        }

        // add extended fields (with obj. prefix too)
        if (part instanceof MimeMessage) {
            final MimeMessage message = (MimeMessage) part;
            try {
                final Address[] address = message.getRecipients(MimeMessage.RecipientType.BCC);
                ret.put(OBJECT_PREFIX + "Recipients.BCC", address);
            } catch (final MessagingException e) {
                log.debug(e.getLocalizedMessage(), e);
            }
            try {
                final Address[] address = message.getRecipients(MimeMessage.RecipientType.CC);
                ret.put(OBJECT_PREFIX + "Recipients.CC", address);
            } catch (final MessagingException e) {
                log.debug(e.getLocalizedMessage(), e);
            }
            try {
                final Address[] address = message.getRecipients(MimeMessage.RecipientType.TO);
                ret.put(OBJECT_PREFIX + "Recipients.TO", address);
            } catch (final MessagingException e) {
                log.debug(e.getLocalizedMessage(), e);
            }
            try {
                final Address[] address = message.getRecipients(MimeMessage.RecipientType.NEWSGROUPS);
                ret.put(OBJECT_PREFIX + "Recipients.NEWSGROUPS", address);
            } catch (final MessagingException e) {
                log.debug(e.getLocalizedMessage(), e);
            }
        }

        return ret;
    }

    @Override
    public int size() {
        return getMap().size();
    }

    @Override
    public boolean isEmpty() {
        return getMap().size() < 1;
    }

    @Override
    public boolean containsKey(final Object key) {
        return getMap().containsKey(key);
    }

    @Override
    public boolean containsValue(final Object value) {
        return getMap().containsValue(value);
    }

    @Override
    public Object get(final Object key) {
        return getMap().get(key);
    }

    @Override
    public Object put(final String key, final Object value) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Object remove(final Object key) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void putAll(final Map<? extends String, ? extends Object> t) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void clear() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Set<String> keySet() {
        return Collections.unmodifiableSet(getMap().keySet());
    }

    @Override
    public Collection<Object> values() {
        return Collections.unmodifiableCollection(getMap().values());
    }

    @Override
    public Set<Entry<String, Object>> entrySet() {
        return Collections.unmodifiableSet(getMap().entrySet());
    }
}
