/**
 * Copyright (C) 1999-2010 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.sparkimpl.preference.notifications;

import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smackx.vcardtemp.packet.VCard;
import org.jivesoftware.spark.PresenceManager;
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 javax.swing.*;

import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;

import static java.awt.GridBagConstraints.*;
import static java.awt.GridBagConstraints.BOTH;

public class NotificationAlertUI extends JPanel {
    private final JLabel avatarLabel = new JLabel();
    private final JLabel titleLabel = new JLabel();
    private final JLabel emailAddressLabel = new JLabel();
    private final JLabel professionLabel = new JLabel();

    private final VCard vcard;
    private final BareJid jid;

    private final boolean available;

    final JLabel topLabel = new JLabel();
    
    private static final int AVATAR_HEIGHT = Sizes.Avatar.NOTIFICATION;
    private static final int AVATAR_WIDTH = Sizes.Avatar.NOTIFICATION;

    private static final Color COLOR_NOTIFICATION_TITLE = new Color(64, 103, 162);
    private static final Color COLOR_INNER_BLOCK_BORDER = new Color(197, 213, 230);
    private static final Color COLOR_LINK = new Color(49, 89, 151);
    private static final Color COLOR_GRADIENT = new Color(233, 240, 247);

    public NotificationAlertUI(BareJid jid, boolean available, Presence presence) {
        setLayout(new GridBagLayout());
        this.available = available;
        this.jid = jid;
        vcard = SparkManager.getVCardManager().getVCard(jid);
        final Icon presenceIcon = PresenceManager.getIconFromPresence(presence);

        topLabel.setIcon(presenceIcon);
        topLabel.setHorizontalTextPosition(JLabel.RIGHT);
        topLabel.setFont(new Font("Dialog", Font.BOLD, 15));
        topLabel.setForeground(Color.DARK_GRAY);

        // Add Caller Block
        buildInnerBlock();
    }


    /**
     * Builds the part of the incoming call UI with the Callers information.
     */
    private void buildInnerBlock() {
        final JPanel panel = new JPanel(new GridBagLayout());
        panel.setBackground(Color.white);
        panel.setBorder(BorderFactory.createLineBorder(COLOR_INNER_BLOCK_BORDER, 1));

        titleLabel.setHorizontalTextPosition(JLabel.RIGHT);
        // Add Avatar
        panel.add(avatarLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 1.0, NORTHWEST, NONE, new Insets(10, 15, 5, 0), 0, 0));
        // Add Avatar information
        panel.add(titleLabel, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, NORTHWEST, HORIZONTAL, new Insets(10, 5, 0, 0), 0, 0));
        panel.add(professionLabel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, NORTHWEST, HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0));
        panel.add(emailAddressLabel, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, NORTHWEST, HORIZONTAL, new Insets(0, 7, 0, 0), 0, 0));

        // Set default settings
        titleLabel.setForeground(COLOR_NOTIFICATION_TITLE);
        titleLabel.setFont(new Font("Dialog", Font.BOLD, 16));


        if (vcard != null) {
            handleVCardInformation(vcard);
        }
        else {
            updateWithGenericInfo();
        }

        // Add to panel
        add(panel, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, NORTHWEST, BOTH, new Insets(5, 5, 5, 5), 0, 0));
    }


    private void updateWithGenericInfo() {
        String title = SparkManager.getUserManager().getUserNicknameFromJID(jid);

        titleLabel.setText(title);

        avatarLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.DEFAULT_AVATAR_64x64_IMAGE));
        avatarLabel.invalidate();
        avatarLabel.validate();
        avatarLabel.repaint();


        invalidate();
        validate();
        repaint();
    }

    private void handleVCardInformation(VCard vcard) {
        if (vcard.getError() != null) {
            updateWithGenericInfo();
            return;
        }

        // Nickname label should show presence and nickname.
        String nickname = SparkManager.getUserManager().getUserNicknameFromJID(jid);

        String fullName = vcard.getField("FN");
        if (ModelUtil.hasLength(fullName)) {
            titleLabel.setText(fullName);
        }
        else {
            titleLabel.setText(nickname);
        }

        String username = titleLabel.getText();
        String statusMessage = username + " is " + (available ? "Online" : "Offline");
        topLabel.setText(statusMessage);

        String jobTitle = vcard.getField("TITLE");
        if (jobTitle != null) {
            professionLabel.setText(jobTitle);
        }

        String emailAddress = vcard.getEmailHome();
        if (ModelUtil.hasLength(emailAddress)) {
            emailAddressLabel.setText(emailAddress);

            final String unselectedText = "<html><body><font color=" + GraphicUtils.toHTMLColor(COLOR_LINK) + "><u>" + emailAddress + "</u></font></body></html>";
            final String hoverText = "<html><body><font color=red><u>" + emailAddress + "</u></font></body></html>";
            emailAddressLabel.addMouseListener(new MouseAdapter() {
                @Override
				public void mouseEntered(MouseEvent e) {
                    emailAddressLabel.setText(hoverText);
                }

                @Override
				public void mouseExited(MouseEvent e) {
                    emailAddressLabel.setText(unselectedText);
                }
            });
        }

        byte[] avatarBytes = null;
        try {
            avatarBytes = vcard.getAvatar();
        }
        catch (Exception e) {
            Log.error("Cannot retrieve avatar bytes.", e);
        }

        if (avatarBytes != null) {
            try {
                ImageIcon avatarIcon = new ImageIcon(avatarBytes);
                int w = avatarIcon.getIconWidth();
                int h = avatarIcon.getIconHeight();
                double ratio = (double) w / (double) h;
                if (w > 120 || h > 120) {
                    if (w > h) {
                        w = 120;
                        h = (int) (w / ratio);
                    } else {
                        h = 120;
                        w = (int) (h * ratio);
                    }
                }

                BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
                Graphics2D g2 = resizedImg.createGraphics();
                g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                g2.drawImage(avatarIcon.getImage(), 0, 0, w, h, null);
                g2.dispose();

                avatarIcon = new ImageIcon(resizedImg);
                avatarLabel.setIcon(GraphicUtils.scale(avatarIcon, AVATAR_HEIGHT, AVATAR_WIDTH));
            } catch (Exception ignored) {
            }
        }
        else {
            avatarLabel.setIcon(SparkRes.getImageIcon(SparkRes.Icon.DEFAULT_AVATAR_64x64_IMAGE));
        }

        avatarLabel.invalidate();
        avatarLabel.validate();
        avatarLabel.repaint();

        invalidate();
        validate();
        repaint();
    }

    @Override
	public void paintComponent(Graphics g) {
        BufferedImage cache = new BufferedImage(2, getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = cache.createGraphics();

        GradientPaint paint = new GradientPaint(0, 0, COLOR_GRADIENT, 0, getHeight(), Color.white, true);

        g2d.setPaint(paint);
        g2d.fillRect(0, 0, getWidth(), getHeight());
        g2d.dispose();

        g.drawImage(cache, 0, 0, getWidth(), getHeight(), null);
    }
}

