/*
 * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
 *
 * Copyright @ 2015 Atlassian Pty Ltd
 *
 * 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 net.java.sip.communicator.impl.gui.main.chat.toolBars;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.util.List;

import javax.swing.*;

import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.customcontrols.*;
import net.java.sip.communicator.impl.gui.main.call.*;
import net.java.sip.communicator.impl.gui.main.chat.*;
import net.java.sip.communicator.impl.gui.main.chat.conference.*;
import net.java.sip.communicator.impl.gui.main.configforms.*;
import net.java.sip.communicator.impl.gui.main.contactlist.*;
import net.java.sip.communicator.impl.gui.main.contactlist.contactsource.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.plugin.desktoputil.*;
import net.java.sip.communicator.plugin.desktoputil.SwingWorker;
import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.gui.Container;
import net.java.sip.communicator.service.muc.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.call.*;
import net.java.sip.communicator.util.skin.*;

/**
 * The <tt>MainToolBar</tt> is a <tt>JToolBar</tt> which contains buttons
 * for file operations, like save and print, for copy-paste operations, etc.
 * It's the main toolbar in the <tt>ChatWindow</tt>. It contains only
 * <tt>ChatToolbarButton</tt>s, which have a specific background icon and
 * rollover behaviour to differentiates them from normal buttons.
 *
 * @author Yana Stamcheva
 * @author Lubomir Marinov
 * @author Adam Netocny
 */
public class MainToolBar
    extends TransparentPanel
    implements ActionListener,
               ChatChangeListener,
               ChatSessionChangeListener,
               ChatRoomLocalUserRoleListener,
               Skinnable
{
    /**
     * Serial version UID.
     */
    private static final long serialVersionUID = -5572510509556499465L;

    /**
     * The invite button.
     */
    private final ChatToolbarButton inviteButton
        = new ChatToolbarButton(
                ImageLoader.getImage(ImageLoader.ADD_TO_CHAT_ICON));

    /**
     * The history button.
     */
    private final HistorySelectorBox historyButton;

    /**
     * The send file button.
     */
    private final ChatToolbarButton sendFileButton
        = new ChatToolbarButton(
                ImageLoader.getImage(ImageLoader.SEND_FILE_ICON));

    /**
     * The button showing the previous page of the chat history.
     */
    private final ChatToolbarButton previousButton
        = new ChatToolbarButton(
                ImageLoader.getImage(ImageLoader.PREVIOUS_ICON));

    /**
     * The button showing the next page from chat history.
     */
    private final ChatToolbarButton nextButton
        = new ChatToolbarButton(
                ImageLoader.getImage(ImageLoader.NEXT_ICON));

    /**
     * The leave chat room button.
     */
    private final ChatToolbarButton leaveChatRoomButton
        = new ChatToolbarButton(
                ImageLoader.getImage(ImageLoader.LEAVE_ICON));

    /**
     * The call button.
     */
    private final ChatToolbarButton callButton
        = new ChatToolbarButton(
                ImageLoader.getImage(ImageLoader.CHAT_CALL));

    /**
     * The call button.
     */
    private final ChatToolbarButton callVideoButton
        = new ChatToolbarButton(
                ImageLoader.getImage(ImageLoader.CHAT_VIDEO_CALL));

    /**
     * The options button.
     */
    private final ChatToolbarButton optionsButton
            = new ChatToolbarButton(
                    ImageLoader.getImage(ImageLoader.CHAT_CONFIGURE_ICON));

    /**
     * The desktop sharing button.
     */
    private final ChatToolbarButton desktopSharingButton
        = new ChatToolbarButton(
                ImageLoader.getImage(ImageLoader.CHAT_DESKTOP_SHARING));

    /**
     * The font button.
     */
    private final ChatToolbarButton fontButton
        = new ChatToolbarButton(
                ImageLoader.getImage(ImageLoader.FONT_ICON));

    private SmileysSelectorBox smileysBox;

    /**
     * The current <tt>ChatSession</tt> made known to this instance by the last
     * call to its {@link #chatChanged(ChatPanel)}.
     */
    private ChatSession chatSession;

    /**
     * The chat container, where this tool bar is added.
     */
    protected final ChatContainer chatContainer;

    /**
     * The plug-in container contained in this tool bar.
     */
    private final PluginContainer pluginContainer;

    /**
     * The phone util used to enable/disable buttons.
     */
    private MetaContactPhoneUtil contactPhoneUtil = null;

    /**
     * Creates an instance and constructs the <tt>MainToolBar</tt>.
     *
     * @param chatContainer The parent <tt>ChatWindow</tt>.
     */
    public MainToolBar(ChatContainer chatContainer)
    {
        this.chatContainer = chatContainer;

        historyButton = new HistorySelectorBox(chatContainer);

        init();

        pluginContainer
            = new PluginContainer(this, Container.CONTAINER_CHAT_TOOL_BAR);

        this.chatContainer.addChatChangeListener(this);

    }

    /**
     * Initializes this component.
     */
    protected void init()
    {
        this.setLayout(new FlowLayout(FlowLayout.LEFT, 3, 0));
        this.setOpaque(false);

        this.add(inviteButton);

        // if we leave a chat room when we close the window
        // there is no need for this button
        if(!ConfigurationUtils.isLeaveChatRoomOnWindowCloseEnabled())
            this.add(leaveChatRoomButton);

        this.add(callButton);
        this.add(callVideoButton);
        this.add(desktopSharingButton);
        this.add(sendFileButton);

        ChatPanel chatPanel = chatContainer.getCurrentChat();
        if (chatPanel == null
            || !(chatPanel.getChatSession() instanceof MetaContactChatSession))
            sendFileButton.setEnabled(false);
        
        if(chatPanel != null && chatPanel.isPrivateMessagingChat())
        {
            inviteButton.setEnabled(false);
        }

        if (chatPanel == null
            || !(chatPanel.getChatSession() instanceof ConferenceChatSession))
            desktopSharingButton.setEnabled(false);
        
        this.addSeparator();

        SIPCommMenuBar historyMenuBar = new SIPCommMenuBar();
        historyMenuBar.setOpaque(false);
        historyMenuBar.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
        historyMenuBar.add(historyButton);
        this.add(historyMenuBar);

        this.add(previousButton);
        this.add(nextButton);

        // We only add the options button if the property SHOW_OPTIONS_WINDOW
        // specifies so or if it's not set.
        Boolean showOptionsProp
            = GuiActivator.getConfigurationService()
                .getBoolean(ConfigurationFrame.SHOW_OPTIONS_WINDOW_PROPERTY,
                            false);

        if (showOptionsProp.booleanValue())
        {
            this.add(optionsButton);
        }

        this.addSeparator();

        if(ConfigurationUtils.isFontSupportEnabled())
        {
            this.add(fontButton);
            fontButton.setName("font");
            fontButton.setToolTipText(GuiActivator.getResources()
                .getI18NString("service.gui.CHANGE_FONT"));
            fontButton.addActionListener(this);
        }

        initSmiliesSelectorBox();

        this.addSeparator();

        this.inviteButton.setName("invite");
        this.inviteButton.setToolTipText(
            GuiActivator.getResources().getI18NString("service.gui.INVITE"));

        this.leaveChatRoomButton.setName("leave");
        this.leaveChatRoomButton.setToolTipText(
            GuiActivator.getResources().getI18NString("service.gui.LEAVE"));

        setCallButtonsName();
        setCallButtonsIcons();
        
        this.desktopSharingButton.setName("desktop");
        this.desktopSharingButton.setToolTipText(
            GuiActivator.getResources().getI18NString(
                "service.gui.SHARE_DESKTOP_WITH_CONTACT"));

        optionsButton.setName("options");
        optionsButton.setToolTipText(
            GuiActivator.getResources().getI18NString("service.gui.OPTIONS"));

        this.sendFileButton.setName("sendFile");
        this.sendFileButton.setToolTipText(
            GuiActivator.getResources().getI18NString("service.gui.SEND_FILE"));

        this.previousButton.setName("previous");
        this.previousButton.setToolTipText(
            GuiActivator.getResources().getI18NString("service.gui.PREVIOUS"));

        this.nextButton.setName("next");
        this.nextButton.setToolTipText(
            GuiActivator.getResources().getI18NString("service.gui.NEXT"));

        inviteButton.addActionListener(this);
        leaveChatRoomButton.addActionListener(this);
        callButton.addActionListener(this);
        callVideoButton.addActionListener(this);
        desktopSharingButton.addActionListener(this);
        optionsButton.addActionListener(this);
        sendFileButton.addActionListener(this);
        previousButton.addActionListener(this);
        nextButton.addActionListener(this);
    }

    private void initSmiliesSelectorBox()
    {
        this.smileysBox = new SmileysSelectorBox();

        this.smileysBox.setName("smiley");
        this.smileysBox.setToolTipText(GuiActivator.getResources()
            .getI18NString("service.gui.INSERT_SMILEY") + " Ctrl-M");

        SIPCommMenuBar smileyMenuBar = new SIPCommMenuBar();
        smileyMenuBar.setOpaque(false);
        smileyMenuBar.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
        smileyMenuBar.add(smileysBox);

        this.add(smileyMenuBar);
    }

    /**
     * Runs clean-up for associated resources which need explicit disposal (e.g.
     * listeners keeping this instance alive because they were added to the
     * model which operationally outlives this instance).
     */
    public void dispose()
    {
        pluginContainer.dispose();

        historyButton.dispose();

        if (this.chatSession != null
            && this.chatSession instanceof MetaContactChatSession)
            this.chatSession.removeChatTransportChangeListener(this);

        if(this.chatSession != null
            && this.chatSession instanceof ConferenceChatSession)
            ((ConferenceChatSession) this.chatSession)
                .removeLocalUserRoleListener(this);
    }

    /**
     * Implements ChatChangeListener#chatChanged(ChatPanel).
     * @param chatPanel the <tt>ChatPanel</tt>, which changed
     */
    public void chatChanged(ChatPanel chatPanel)
    {
        if (chatPanel == null)
        {
            setChatSession(null);
        }
        else
        {
            MetaContact contact
                = GuiActivator.getUIService().getChatContact(chatPanel);

            for (PluginComponent c : pluginContainer.getPluginComponents())
                c.setCurrentContact(contact);

            ChatSession chatSession = chatPanel.getChatSession();
            setChatSession(chatSession);

            leaveChatRoomButton.setEnabled(
                chatSession instanceof ConferenceChatSession);
            
            desktopSharingButton.setEnabled(
                !(chatSession instanceof ConferenceChatSession));

            inviteButton.setEnabled(
                chatPanel.findInviteChatTransport() != null);

            sendFileButton.setEnabled(
                chatPanel.findFileTransferChatTransport() != null);
            inviteButton.setEnabled(!chatPanel.isPrivateMessagingChat());

            if(chatSession instanceof ConferenceChatSession)
            {
                updateInviteContactButton();

                callButton.setVisible(false);
                callVideoButton.setVisible(false);
                callButton.setEnabled(true);
                callVideoButton.setEnabled(true);
            }
            else if(contact != null)
            {
                callButton.setVisible(true);
                callVideoButton.setVisible(true);
                new UpdateCallButtonWorker(contact).start();
            }

            changeHistoryButtonsState(chatPanel);
            
            setCallButtonsName();
            setCallButtonsIcons();

            currentChatTransportChanged(chatSession);
        }
    }

    /**
     * Returns list of <tt>ChatTransport</tt> (i.e. contact) that supports the
     * specified <tt>OperationSet</tt>.
     *
     * @param transports list of <tt>ChatTransport</tt>
     * @param opSetClass <tt>OperationSet</tt> to find
     * @return list of <tt>ChatTransport</tt> (i.e. contact) that supports the
     * specified <tt>OperationSet</tt>.
     */
    private List<ChatTransport> getOperationSetForCapabilities(
            List<ChatTransport> transports,
            Class<? extends OperationSet> opSetClass)
    {
        List<ChatTransport> list = new ArrayList<ChatTransport>();

        for(ChatTransport transport : transports)
        {
            ProtocolProviderService protocolProvider
                = transport.getProtocolProvider();
            OperationSetContactCapabilities capOpSet
                = protocolProvider.getOperationSet(
                        OperationSetContactCapabilities.class);
            OperationSetPersistentPresence presOpSet
                = protocolProvider.getOperationSet(
                        OperationSetPersistentPresence.class);

            if (capOpSet == null)
            {
                list.add(transport);
            }
            else if (presOpSet != null)
            {
                Contact contact
                    = presOpSet.findContactByID(transport.getName());

                if((contact != null)
                        && (capOpSet.getOperationSet(contact, opSetClass)
                                != null))
                {
                    // It supports OpSet for at least one of its
                    // ChatTransports
                    list.add(transport);
                }
            }
        }

        return list;
    }

    /**
     * Implements
     * ChatSessionChangeListener#currentChatTransportChanged(ChatSession).
     * @param chatSession the <tt>ChatSession</tt>, which transport has changed
     */
    public void currentChatTransportChanged(ChatSession chatSession)
    {
        if (chatSession == null)
            return;

        ChatTransport currentTransport = chatSession.getCurrentChatTransport();
        Object currentDescriptor = currentTransport.getDescriptor();

        if (currentDescriptor instanceof Contact)
        {
            Contact contact = (Contact) currentDescriptor;

            for (PluginComponent c : pluginContainer.getPluginComponents())
                c.setCurrentContact(contact, currentTransport.getResourceName());
        }
    }

    /**
     * When a property of the chatTransport has changed.
     * @param eventID the event id representing the property of the transport
     * that has changed.
     */
    public void currentChatTransportUpdated(int eventID)
    {}

    /**
     * Handles the <tt>ActionEvent</tt>, when one of the tool bar buttons is
     * clicked.
     * @param e the <tt>ActionEvent</tt> that notified us
     */
    public void actionPerformed(ActionEvent e)
    {
        AbstractButton button = (AbstractButton) e.getSource();
        String buttonText = button.getName();

        ChatPanel chatPanel = chatContainer.getCurrentChat();

        if (buttonText.equals("previous"))
        {
            chatPanel.loadPreviousPageFromHistory();
        }
        else if (buttonText.equals("next"))
        {
            chatPanel.loadNextPageFromHistory();
        }
        else if (buttonText.equals("sendFile"))
        {
            SipCommFileChooser scfc = GenericFileDialog.create(
                null, "Send file...", SipCommFileChooser.LOAD_FILE_OPERATION,
                    ConfigurationUtils.getSendFileLastDir());
            File selectedFile = scfc.getFileFromDialog();
            if(selectedFile != null)
            {
                ConfigurationUtils.setSendFileLastDir(
                    selectedFile.getParent());
                chatContainer.getCurrentChat().sendFile(selectedFile);
            }
        }
        else if (buttonText.equals("invite"))
        {
            ChatInviteDialog inviteDialog = new ChatInviteDialog(chatPanel);

            inviteDialog.setVisible(true);
        }
        else if (buttonText.equals("leave"))
        {
            ChatRoomWrapper chatRoomWrapper 
                = (ChatRoomWrapper)chatPanel.getChatSession().getDescriptor();
            ChatRoomWrapper leavedRoomWrapped 
                = GuiActivator.getMUCService().leaveChatRoom(
                    chatRoomWrapper);
        }
        else if (buttonText.equals("call"))
        {
            call(false, false);
        }
        else if (buttonText.equals("callVideo"))
        {
            call(true, false);
        }
        else if (buttonText.equals("desktop"))
        {
            call(true, true);
        }
        else if (buttonText.equals("options"))
        {
            GuiActivator.getUIService()
                .getConfigurationContainer().setVisible(true);
        }
        else if (buttonText.equals("font"))
            chatPanel.showFontChooserDialog();
        else if (buttonText.equals("createConference"))
        {
            chatPanel.showChatConferenceDialog();
        }
    }

    /**
     * Returns the button used to show the history window.
     *
     * @return the button used to show the history window.
     */
    public HistorySelectorBox getHistoryButton()
    {
        return historyButton;
    }

    /**
     * Get the smileys box.
     *
     * @return the smileys box
     */
    public SmileysSelectorBox getSmileysBox()
    {
        return smileysBox;
    }

    /**
     * Disables/Enables history arrow buttons depending on whether the
     * current page is the first, the last page or a middle page.
     * @param chatPanel the <tt>ChatPanel</tt> which has provoked the change.
     */
    public void changeHistoryButtonsState(ChatPanel chatPanel)
    {
        ChatConversationPanel convPanel = chatPanel.getChatConversationPanel();

        long firstMsgInHistory = chatPanel
            .getFirstHistoryMsgTimestamp().getTime();
        long lastMsgInHistory = chatPanel
            .getLastHistoryMsgTimestamp().getTime();
        Date firstMsgInPage = convPanel.getPageFirstMsgTimestamp();
        Date lastMsgInPage = convPanel.getPageLastMsgTimestamp();

        if(firstMsgInHistory == 0 || lastMsgInHistory == 0)
        {
            previousButton.setEnabled(false);
            nextButton.setEnabled(false);
            return;
        }

        previousButton.setEnabled(firstMsgInHistory < firstMsgInPage.getTime());

        nextButton
            .setEnabled(
                (lastMsgInPage.getTime() > 0)
                    && (lastMsgInHistory > lastMsgInPage.getTime()));
    }

    /**
     * Sets the current <tt>ChatSession</tt> made known to this instance by the
     * last call to its {@link #chatChanged(ChatPanel)}.
     *
     * @param chatSession the <tt>ChatSession</tt> to become current for this
     * instance
     */
    private void setChatSession(ChatSession chatSession)
    {
        if (this.chatSession != chatSession)
        {
            if (this.chatSession instanceof MetaContactChatSession)
                this.chatSession.removeChatTransportChangeListener(this);

            if(this.chatSession instanceof ConferenceChatSession)
                ((ConferenceChatSession) this.chatSession)
                    .removeLocalUserRoleListener(this);

            this.chatSession = chatSession;

            if (this.chatSession instanceof MetaContactChatSession)
                this.chatSession.addChatTransportChangeListener(this);

            if(this.chatSession instanceof ConferenceChatSession)
                ((ConferenceChatSession) this.chatSession)
                    .addLocalUserRoleListener(this);
        }
    }

    /**
     * Adds a separator to this tool bar.
     */
    private void addSeparator()
    {
        this.add(new JSeparator(SwingConstants.VERTICAL));
    }

    /**
     * Reloads icons for buttons.
     */
    public void loadSkin()
    {
        inviteButton.setIconImage(ImageLoader.getImage(
                ImageLoader.ADD_TO_CHAT_ICON));

        historyButton.loadSkin();

        sendFileButton.setIconImage(ImageLoader.getImage(
                ImageLoader.SEND_FILE_ICON));

        fontButton.setIconImage(ImageLoader.getImage(
                ImageLoader.FONT_ICON));

        previousButton.setIconImage(ImageLoader.getImage(
                ImageLoader.PREVIOUS_ICON));

        nextButton.setIconImage(ImageLoader.getImage(
                ImageLoader.NEXT_ICON));

        leaveChatRoomButton.setIconImage(ImageLoader.getImage(
                ImageLoader.LEAVE_ICON));

        desktopSharingButton.setIconImage(ImageLoader.getImage(
            ImageLoader.CHAT_DESKTOP_SHARING));

        optionsButton.setIconImage(ImageLoader.getImage(
                ImageLoader.CHAT_CONFIGURE_ICON));
        
        setCallButtonsIcons();
    }

    /**
     * Establishes a call.
     *
     * @param isVideo indicates if a video call should be established.
     * @param isDesktopSharing indicates if a desktopSharing should be
     * established.
     */
    private void call(boolean isVideo, boolean isDesktopSharing)
    {
        ChatPanel chatPanel = chatContainer.getCurrentChat();

        ChatSession chatSession = chatPanel.getChatSession();

        Class<? extends OperationSet> opSetClass;
        if(isVideo)
        {
            if(isDesktopSharing)
                opSetClass = OperationSetDesktopStreaming.class;
            else
                opSetClass = OperationSetVideoTelephony.class;
        }
        else
            opSetClass = OperationSetBasicTelephony.class;

        List<ChatTransport> telTransports = null;
        if (chatSession != null)
            telTransports = chatSession
                .getTransportsForOperationSet(opSetClass);

        List<ChatTransport> contactOpSetSupported;

        contactOpSetSupported =
            getOperationSetForCapabilities(telTransports, opSetClass);

        List<UIContactDetail> res = new ArrayList<UIContactDetail>();
        for(ChatTransport ct : contactOpSetSupported)
        {
            HashMap<Class<? extends OperationSet>, ProtocolProviderService> m =
                new HashMap<Class<? extends OperationSet>,
                            ProtocolProviderService>();
            m.put(opSetClass, ct.getProtocolProvider());

            UIContactDetailImpl d = new UIContactDetailImpl(
                                                ct.getName() + (ct.getResourceName() == null
                                                    ? ""
                                                    : "/" + ct.getResourceName()),
                                                ct.getDisplayName(),
                                                null,
                                                (ct.getResourceName() == null
                                                    ? Arrays.asList(GuiActivator.getResources().getI18NString("service.gui.VIA") + ": "
                                                        + ct.getProtocolProvider().getAccountID().getAccountAddress())
                                                    : null),
                                                null,
                                                m,
                                                null,
                                                ct);
            PresenceStatus status = ct.getStatus();
            byte[] statusIconBytes = status.getStatusIcon();

            if (statusIconBytes != null && statusIconBytes.length > 0)
            {
                d.setStatusIcon(new ImageIcon(
                    ImageLoader.getIndexedProtocolImage(
                        ImageUtils.getBytesInImage(statusIconBytes),
                        ct.getProtocolProvider())));
            }

            res.add(d);
        }
        
        Point location = new Point(callButton.getX(),
            callButton.getY() + callButton.getHeight());

        SwingUtilities.convertPointToScreen(
            location, this);

        MetaContact metaContact
            = GuiActivator.getUIService().getChatContact(chatPanel);
        UIContactImpl uiContact = null;
        if (metaContact != null)
            uiContact = MetaContactListSource.getUIContact(metaContact);

        CallManager.call(
            res,
            uiContact,
            isVideo,
            isDesktopSharing,
            callButton,
            location);
    }

    /**
     * Sets the names of the call buttons depending on the chat session type.
     */
    private void setCallButtonsName()
    {
        if(chatSession instanceof ConferenceChatSession)
        {
            callButton.setName("createConference");
            callVideoButton.setName("createConference");
            this.callButton.setToolTipText(
                GuiActivator.getResources().getI18NString(
                    "service.gui.CREATE_JOIN_VIDEO_CONFERENCE"));

            this.callVideoButton.setToolTipText(
                GuiActivator.getResources().getI18NString(
                    "service.gui.CREATE_JOIN_VIDEO_CONFERENCE"));
        }
        else
        {
            callButton.setName("call");
            callVideoButton.setName("callVideo");
            this.callButton.setToolTipText(
                GuiActivator.getResources().getI18NString(
                    "service.gui.CALL_CONTACT"));

            this.callVideoButton.setToolTipText(
                GuiActivator.getResources().getI18NString(
                    "service.gui.CALL_CONTACT"));
        }
    }

    /**
     * Sets the icons of the call buttons depending on the chat session type.
     */
    private void setCallButtonsIcons()
    {
        if(chatSession instanceof ConferenceChatSession)
        {
            callButton.setIconImage(ImageLoader.getImage(
                ImageLoader.CHAT_ROOM_CALL));
            callVideoButton.setIconImage(ImageLoader.getImage(
                ImageLoader.CHAT_ROOM_VIDEO_CALL));
            callButton.setPreferredSize(new Dimension(29, 25));
            callVideoButton.setPreferredSize(new Dimension(29, 25));
        }
        else
        {
            callButton.setIconImage(ImageLoader.getImage(
                ImageLoader.CHAT_CALL));
            callVideoButton.setIconImage(ImageLoader.getImage(
                ImageLoader.CHAT_VIDEO_CALL));
            callButton.setPreferredSize(new Dimension(25, 25));
            callVideoButton.setPreferredSize(new Dimension(25, 25));
        }
        callButton.repaint();
        callVideoButton.repaint();
    }

    /**
     * Fired when local user role has changed.
     * @param evt the <tt>ChatRoomLocalUserRoleChangeEvent</tt> instance
     */
    @Override
    public void localUserRoleChanged(ChatRoomLocalUserRoleChangeEvent evt)
    {
        updateInviteContactButton();
    }

    /**
     * Updates invite contact button depending on the user role we have.
     */
    private void updateInviteContactButton()
    {
        if(chatSession instanceof ConferenceChatSession)
        {
            ChatRoomMemberRole role =
                ((ChatRoomWrapper)chatSession.getDescriptor())
                    .getChatRoom().getUserRole();

            // it means we are at least a moderator
            inviteButton.setEnabled(role.getRoleIndex() >= 50);
        }
    }

    /**
     * Searches for phone numbers in <tt>MetaContact/tt> operation sets.
     * And changes the call button enable/disable state.
     */
    private class UpdateCallButtonWorker
        extends SwingWorker
    {
        /**
         * The current contact.
         */
        private MetaContact contact;

        /**
         * Has this contact any phone.
         */
        private boolean isCallEnabled = false;

        /**
         * Has this contact any video phone.
         */
        private boolean isVideoCallEnabled = false;

        /**
         * Has this contact has desktop sharing enabled.
         */
        private boolean isDesktopSharingEnabled = false;

        /**
         * Creates worker.
         * @param contact
         */
        UpdateCallButtonWorker(MetaContact contact)
        {
            this.contact = contact;
        }

        /**
         * Executes in worker thread.
         * @return
         * @throws Exception
         */
        @Override
        protected Object construct()
            throws
            Exception
        {
            contactPhoneUtil = MetaContactPhoneUtil.getPhoneUtil(contact);

            isCallEnabled = contactPhoneUtil.isCallEnabled();
            isVideoCallEnabled = contactPhoneUtil.isVideoCallEnabled();
            isDesktopSharingEnabled = contactPhoneUtil.isDesktopSharingEnabled();

            return null;
        }

        /**
         * Called on the event dispatching thread (not on the worker thread)
         * after the <code>construct</code> method has returned.
         */
        @Override
        protected void finished()
        {
            callButton.setEnabled(isCallEnabled);
            callVideoButton.setEnabled(isVideoCallEnabled);
            desktopSharingButton.setEnabled(isDesktopSharingEnabled);
        }

    }
}
