/**
 * Copyright (C) 2004-2011 Jive Software. All rights reserved.
 *
 * Licensed 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.jivesoftware.spark.ui;

import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.smackx.vcardtemp.packet.VCard;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.util.GraphicUtils;
import org.jivesoftware.spark.util.ModelUtil;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.sparkimpl.settings.Sizes;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.EntityBareJid;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;
import javax.swing.Timer;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import static org.jivesoftware.spark.util.XEP0392Utils.colorOfContact;

/**
 * UI to display VCard Information in Wizards, Dialogs, Chat Rooms and any other container.
 *
 * @author Derek DeMoro
 */
public class VCardPanel extends JPanel {
	private final Cursor DEFAULT_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR);
    private final Cursor LINK_CURSOR = new Cursor(Cursor.HAND_CURSOR);

    private final JWindow _avatarHoverWindow = new JWindow();
    private final BareJid jid;
    private final JLabel avatarImage;

    private String emailAddress = "";

    /**
     * Generate a VCard Panel using the specified jid.
     */
    public VCardPanel(final EntityBareJid jid) {
        setLayout(new GridBagLayout());
        setOpaque(false);

        this.jid = jid;
        avatarImage = new JLabel();
        add(avatarImage, new GridBagConstraints(0, 0, 1, 3, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 0, 5, 0), 0, 0));
        buildAvatarHover();

        VCard vcard = SparkManager.getVCardManager().getVCard(jid);
        if (vcard == null) {
            // Do nothing.
            return;
        }

        ImageIcon icon = null;

        byte[] bytes = vcard.getAvatar();
        if (bytes != null && bytes.length > 0) {
            try {
                icon = new ImageIcon(bytes);
                Image newImage = icon.getImage();
                if (icon.getIconHeight() > Sizes.Avatar.VCARD || icon.getIconWidth() > Sizes.Avatar.VCARD) {
                    newImage = newImage.getScaledInstance(-1, Sizes.Avatar.VCARD, Image.SCALE_SMOOTH);
                }
                icon = new ImageIcon(newImage);
            }
            catch (Exception e) {
                Log.error("Unable to fetch image in vcard!", e);
            }
        }
        else {
            icon = SparkRes.getImageIcon(SparkRes.Icon.DEFAULT_AVATAR_64x64_IMAGE);
        }

        if (icon != null && icon.getIconWidth() > 0) {
            avatarImage.setIcon(icon);
            avatarImage.setBorder(BorderFactory.createLineBorder(Color.lightGray, 1, true));
        }

        buildUI(vcard);
    }
    
    
    private void buildAvatarHover() {
        _avatarHoverWindow.addMouseListener(new MouseAdapter() {
            @Override
			public void mouseExited(MouseEvent e) {
                showAvatarBig(false, null);

            }
        });
    }

    private void showAvatarBig(boolean bool, VCard vcard) {
        if (bool && !_avatarHoverWindow.isVisible()) {
            _avatarHoverWindow.setLocation(avatarImage.getLocationOnScreen().x+2,avatarImage.getLocationOnScreen().y+2);
            _avatarHoverWindow.setVisible(true);
            ImageIcon icon = null;
            JLabel label = new JLabel();
            _avatarHoverWindow.add(label);
            byte[] bytes = vcard.getAvatar();
            Image newImage;
            if (bytes != null && bytes.length > 0) {
                try {
                    icon = new ImageIcon(bytes);
                    newImage = icon.getImage();
                    if (icon.getIconHeight() > Sizes.Avatar.HOVER_BIG || icon.getIconWidth() > Sizes.Avatar.HOVER_BIG) {
                        newImage = newImage.getScaledInstance(-1, Sizes.Avatar.HOVER_BIG, Image.SCALE_SMOOTH);
                    }
                    icon = new ImageIcon(newImage);

                } catch (Exception e1) {
                    Log.error("Unable to process vcard avatar", e1);
                }

            } else {
                icon = SparkRes.getImageIcon(SparkRes.Icon.DEFAULT_AVATAR_32x32_IMAGE);
            }

            label.setIcon(icon);
            _avatarHoverWindow.pack();
            _avatarHoverWindow.invalidate();
            _avatarHoverWindow.validate();
            _avatarHoverWindow.repaint();
        } else {
            _avatarHoverWindow.setVisible(false);
        }
    }

    private void buildUI(final VCard vcard) {
        avatarImage.addMouseListener(new MouseAdapter() {
            @Override
			public void mouseClicked(MouseEvent mouseEvent) {
                if (mouseEvent.getClickCount() == 2) {
                    SparkManager.getVCardManager().viewProfile(jid, avatarImage);
                }
            }
            final Timer timer = new Timer(500, actionEvent -> showAvatarBig(true, vcard) );
            @Override
            public void mouseEntered(MouseEvent e) {
                super.mouseEntered(e);
                timer.start();
            }

            @Override
            public void mouseExited(MouseEvent e) {
                super.mouseExited(e);
                timer.stop();
            }
        });

        String fullName = vcard.getField("FN");

        final JLabel usernameLabel = new JLabel();
        usernameLabel.setHorizontalTextPosition(JLabel.LEFT);
        usernameLabel.setFont(new Font("Dialog", Font.BOLD, 15));
        usernameLabel.setForeground(colorOfContact(jid));
        if (ModelUtil.hasLength(fullName)) {
            usernameLabel.setText(fullName);
        }
        else {
            String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid);
            usernameLabel.setText(nickname);
        }
        usernameLabel.setToolTipText("xmpp:" + jid);

        Icon icon = SparkManager.getChatManager().getIconForContactHandler(jid);
        if (icon != null) {
            usernameLabel.setIcon(icon);
        }

        add(usernameLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 0), 0, 0));

        String title = vcard.getField("TITLE");
        if (ModelUtil.hasLength(title)) {
            final JLabel titleLabel = new JLabel(title);
            titleLabel.setFont(new Font("Dialog", Font.PLAIN, 11));
            add(titleLabel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0));
        }

        if (ModelUtil.hasLength(vcard.getEmailHome())) {
            emailAddress = vcard.getEmailHome();
        }

        final Color linkColor = new Color(49, 89, 151);
        final String unselectedText = "<html><body><font color=" + GraphicUtils.toHTMLColor(linkColor) + "><u>" + emailAddress + "</u></font></body></html>";
        final String hoverText = "<html><body><font color=red><u>" + emailAddress + "</u></font></body></html>";
        final JLabel emailTime = new JLabel(unselectedText);
        emailTime.addMouseListener(new MouseAdapter() {
            @Override
			public void mouseClicked(MouseEvent e) {
                startEmailClient(emailAddress);
            }

            @Override
			public void mouseEntered(MouseEvent e) {
                emailTime.setText(hoverText);
                setCursor(LINK_CURSOR);
            }

            @Override
			public void mouseExited(MouseEvent e) {
                emailTime.setText(unselectedText);
                setCursor(DEFAULT_CURSOR);
            }
        });

        add(emailTime, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 7, 5, 0), 0, 0));
    }

    private void startEmailClient(String emailAddress) {
   		try {
			Desktop.getDesktop().mail(new URI("mailto:" + emailAddress));
		} catch (IOException e) {
			Log.error("Can't open Mailer", e);
		} catch (URISyntaxException e) {
			Log.error("URI Wrong", e);
		}
    }
}
