/*
 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

/*
* Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved.
*  
* JTattoo is multiple licensed. If your are an open source developer you can use
* it under the terms and conditions of the GNU General Public License version 2.0
* or later as published by the Free Software Foundation.
*  
* see: gpl-2.0.txt
* 
* If you pay for a license you will become a registered user who could use the
* software under the terms and conditions of the GNU Lesser General Public License
* version 2.0 or later with classpath exception as published by the Free Software
* Foundation.
* 
* see: lgpl-2.0.txt
* see: classpath-exception.txt
* 
* Registered users could also use JTattoo under the terms and conditions of the 
* Apache License, Version 2.0 as published by the Apache Software Foundation.
*  
* see: APACHE-LICENSE-2.0.txt
*/

package com.jtattoo.plaf;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;

/**
 * This class is a modified copy of the javax.swing.plaf.metal.MetalInternalFrameTitlePane
 *
 * Class that manages a JLF title bar <p>
 *
 * @author Steve Wilson
 * @author Brian Beck
 * @author Michael Hagen
 */
public class BaseInternalFrameTitlePane extends BasicInternalFrameTitlePane implements ActionListener {

    public static final String PAINT_ACTIVE = "paintActive";
    public static final String ICONIFY = "Iconify";
    public static final String MAXIMIZE = "Maximize";
    public static final String CLOSE = "Close";
    protected boolean isPalette = false;
    protected Icon paletteCloseIcon;
    protected int paletteTitleHeight;
    protected int buttonsWidth = 0;
    protected JPanel customTitlePanel;

    public BaseInternalFrameTitlePane(JInternalFrame f) {
        super(f);
    }

    protected void installDefaults() {
        super.installDefaults();
        setFont(UIManager.getFont("InternalFrame.font"));
        paletteTitleHeight = UIManager.getInt("InternalFrame.paletteTitleHeight");
        paletteCloseIcon = UIManager.getIcon("InternalFrame.paletteCloseIcon");
        iconIcon = UIManager.getIcon("InternalFrame.iconifyIcon");
        minIcon = UIManager.getIcon("InternalFrame.minimizeIcon");
        maxIcon = UIManager.getIcon("InternalFrame.maximizeIcon");
        closeIcon = UIManager.getIcon("InternalFrame.closeIcon");
        if (frame.getClientProperty("customTitlePanel") instanceof JPanel) {
            setCustomizedTitlePanel((JPanel)frame.getClientProperty("customTitlePanel"));
        }
    }

    public void setCustomizedTitlePanel(JPanel panel) {
        if (customTitlePanel != null) {
            remove(customTitlePanel);
            customTitlePanel = null;
        }
        if (panel != null) {
            customTitlePanel = panel;
            add(customTitlePanel);
        }
        frame.putClientProperty("customTitlePanel", customTitlePanel);
        revalidate();
        repaint();
    }

    protected void createButtons() {
        iconButton = new BaseTitleButton(iconifyAction, ICONIFY, iconIcon, 1.0f);
        maxButton = new BaseTitleButton(maximizeAction, MAXIMIZE, maxIcon, 1.0f);
        closeButton = new BaseTitleButton(closeAction, CLOSE, closeIcon, 1.0f);
        setButtonIcons();
    }

    protected void setButtonIcons() {
        super.setButtonIcons();
        iconButton.setToolTipText(null);
        maxButton.setToolTipText(null);
        closeButton.setToolTipText(null);
    }

    protected void enableActions() {
        super.enableActions();
        maximizeAction.setEnabled(frame.isMaximizable());
    }

    protected void assembleSystemMenu() {
    }

    protected void addSystemMenuItems(JMenu systemMenu) {
    }

    protected void addSubComponents() {
        add(iconButton);
        add(maxButton);
        add(closeButton);
    }

    protected PropertyChangeListener createPropertyChangeListener() {
        return new BasePropertyChangeHandler();
    }

    protected LayoutManager createLayout() {
        return new BaseTitlePaneLayout();
    }

    protected int getHorSpacing() {
        return 3;
    }

    protected int getVerSpacing() {
        return 3;
    }

    protected boolean centerButtons() {
        return true;
    }

    public void activateFrame() {
    }

    public void deactivateFrame() {
    }

    protected boolean isMacStyleWindowDecoration() {
        return AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn();
    }

    public boolean isActive() {
        return JTattooUtilities.isActive(this);
    }

    public boolean isPalette() {
        return isPalette;
    }

    public void setPalette(boolean b) {
        isPalette = b;
        if (isPalette) {
            closeButton.setIcon(paletteCloseIcon);
            if (frame.isMaximizable()) {
                remove(maxButton);
            }
            if (frame.isIconifiable()) {
                remove(iconButton);
            }
        } else {
            closeButton.setIcon(closeIcon);
            if (frame.isMaximizable()) {
                add(maxButton);
            }
            if (frame.isIconifiable()) {
                add(iconButton);
            }
        }
        revalidate();
        repaint();
    }

    public void actionPerformed(ActionEvent e) {
        AbstractButton button = (AbstractButton) e.getSource();
        button.getModel().setRollover(false);
    }

    public void paintPalette(Graphics g) {
        int width = getWidth();
        int height = getHeight();
        if (JTattooUtilities.isFrameActive(this)) {
            JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 0, 0, width, height);
        } else {
            JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 0, 0, width, height);
        }
    }

    public void paintBackground(Graphics g) {
        if (isActive()) {
            JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowTitleColors(), 0, 0, getWidth(), getHeight());
        } else {
            JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getWindowInactiveTitleColors(), 0, 0, getWidth(), getHeight());
        }
    }

    private Image iconToImage(Icon icon) {
        if (icon instanceof ImageIcon) {
            return ((ImageIcon) icon).getImage();
        } else if (icon != null) {
            int w = icon.getIconWidth();
            int h = icon.getIconHeight();
            BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = image.createGraphics();
            icon.paintIcon(null, g, 0, 0);
            g.dispose();
            return image;
        }
        return null;
    }

    protected int getIconWidth() {
        Image image = iconToImage(frame.getFrameIcon());
        if (image != null) {
            int h = getHeight();
            int ih = image.getHeight(null);
            int iw = image.getWidth(null);
            if (ih > h) {
                double fac = (double) iw / (double) ih;
                ih = h - 1;
                iw = (int) (fac * (double) ih);
            }
            return iw;
        }
        return 0;
    }
    
    protected int paintIcon(Graphics g, int x) {
        Image image = iconToImage(frame.getFrameIcon());
        if (image != null) {
            Graphics2D g2D = (Graphics2D)g;
            Object savedHint = g2D.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
            if (JTattooUtilities.getJavaVersion() >= 1.6) {
                g2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            }
            int h = getHeight();
            int ih = image.getHeight(null);
            int iw = image.getWidth(null);
            if (ih <= h) {
                g2D.drawImage(image, x, (h - ih) / 2, iw, ih, null);
            } else {
                double fac = (double) iw / (double) ih;
                ih = h;
                iw = (int) (fac * (double) ih);
                g2D.drawImage(image, x, 0, iw, ih, null);
            }
            if (savedHint != null) {
                g2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, savedHint);
            }
            return iw;
        }
        return 0;
    }

    public void paintText(Graphics g, int x, int y, String title) {
        if (isActive()) {
            g.setColor(AbstractLookAndFeel.getWindowTitleForegroundColor());
        } else {
            g.setColor(AbstractLookAndFeel.getWindowInactiveTitleForegroundColor());
        }
        JTattooUtilities.drawString(frame, g, title, x, y);
    }

    public void paintBorder(Graphics g) {
        Color borderColor = AbstractLookAndFeel.getWindowInactiveBorderColor();
        if (isActive() || isPalette) {
            borderColor = AbstractLookAndFeel.getWindowBorderColor();
        }
        JTattooUtilities.draw3DBorder(g, ColorHelper.brighter(borderColor, 20), ColorHelper.darker(borderColor, 10), 0, 0, getWidth(), getHeight());
    }

    public void paintComponent(Graphics g) {
        if (isPalette) {
            paintPalette(g);
            return;
        }

        paintBackground(g);

        g.setFont(getFont());
        FontMetrics fm = JTattooUtilities.getFontMetrics(this, g, getFont());
        int width = getWidth();
        int height = getHeight();
        int x = 0;
        int y = ((height - fm.getHeight()) / 2) + fm.getAscent();
        int titleWidth = width - buttonsWidth - 4;
        String frameTitle = frame.getTitle();
        if (JTattooUtilities.isLeftToRight(frame)) {
            if (isMacStyleWindowDecoration()) {
                int iconWidth = getIconWidth();
                titleWidth -= iconWidth + 4;
                frameTitle = JTattooUtilities.getClippedText(frameTitle, fm, titleWidth);
                int titleLength = fm.stringWidth(frameTitle);
                x += buttonsWidth + ((titleWidth - titleLength) / 2);
                paintIcon(g, x);
                x += iconWidth + 4;
            } else {
                int iconWidth = paintIcon(g, x);
                titleWidth -= iconWidth + 4;
                frameTitle = JTattooUtilities.getClippedText(frameTitle, fm, titleWidth);
                if (AbstractLookAndFeel.getTheme().isCenterWindowTitleOn()) {
                    int titleLength = fm.stringWidth(frameTitle);
                    x += iconWidth + 4;
                    x += (titleWidth - titleLength) / 2;
                } else {
                    x += iconWidth + 4;
                }
            }
        } else {
            int iconWidth = getIconWidth();
            if (isMacStyleWindowDecoration()) {
                titleWidth -= iconWidth + 4;
                frameTitle = JTattooUtilities.getClippedText(frameTitle, fm, titleWidth);
                int titleLength = fm.stringWidth(frameTitle);
                x = buttonsWidth + 4 + ((titleWidth - titleLength) / 2);
                paintIcon(g, x + titleLength + 4);
            } else {
                x = width - iconWidth;
                paintIcon(g, x);
                titleWidth -= iconWidth + 4;
                frameTitle = JTattooUtilities.getClippedText(frameTitle, fm, titleWidth);
                int titleLength = fm.stringWidth(frameTitle);
                if (AbstractLookAndFeel.getTheme().isCenterWindowTitleOn()) {
                    x = buttonsWidth + 4 + ((titleWidth - titleLength) / 2);
                } else {
                    x = width - iconWidth - 4 - titleLength;
                }
            }
        }
        paintText(g, x, y, frameTitle);
        
        paintBorder(g);
    }

    class BasePropertyChangeHandler extends BasicInternalFrameTitlePane.PropertyChangeHandler {

        public void propertyChange(PropertyChangeEvent evt) {
            String prop = (String) evt.getPropertyName();
            if (prop.equals(JInternalFrame.IS_SELECTED_PROPERTY)) {
                Boolean b = (Boolean) evt.getNewValue();
                iconButton.putClientProperty(PAINT_ACTIVE, b);
                closeButton.putClientProperty(PAINT_ACTIVE, b);
                maxButton.putClientProperty(PAINT_ACTIVE, b);
                if (b.booleanValue()) {
                    activateFrame();
                } else {
                    deactivateFrame();
                }
                repaint();
            }
            super.propertyChange(evt);
        }
    }

//------------------------------------------------------------------------------
// inner classes
//------------------------------------------------------------------------------
    class BaseTitlePaneLayout extends TitlePaneLayout {

        public void addLayoutComponent(String name, Component c) {
        }

        public void removeLayoutComponent(Component c) {
        }

        public Dimension preferredLayoutSize(Container c) {
            return minimumLayoutSize(c);
        }

        public Dimension minimumLayoutSize(Container c) {
            int width = 30;
            if (frame.isClosable()) {
                width += 21;
            }
            if (frame.isMaximizable()) {
                width += 16 + (frame.isClosable() ? 10 : 4);
            }
            if (frame.isIconifiable()) {
                width += 16 + (frame.isMaximizable() ? 2 : (frame.isClosable() ? 10 : 4));
            }
            FontMetrics fm = JTattooUtilities.getFontMetrics(BaseInternalFrameTitlePane.this, null, getFont());
            String frameTitle = frame.getTitle();
            int title_w = frameTitle != null ? fm.stringWidth(frameTitle) : 0;
            int title_length = frameTitle != null ? frameTitle.length() : 0;

            if (title_length > 2) {
                int subtitle_w = fm.stringWidth(frame.getTitle().substring(0, 2) + "...");
                width += (title_w < subtitle_w) ? title_w : subtitle_w;
            } else {
                width += title_w;
            }

            int height = paletteTitleHeight;
            if (!isPalette) {
                Icon icon = isMacStyleWindowDecoration() ? null : frame.getFrameIcon();
                if (icon == null) {
                    height = Math.max(fm.getHeight() + 6, 16);
                } else {
                    height = Math.max(fm.getHeight() + 6, Math.min(icon.getIconHeight(), 24));
                }
            }
            return new Dimension(width, height);
        }

        public void layoutContainer(Container c) {
            if (AbstractLookAndFeel.getTheme().isMacStyleWindowDecorationOn()) {
                layoutMacStyle(c);
            } else {
                layoutDefault(c);
            }
        }

        public void layoutDefault(Container c) {
            boolean leftToRight = JTattooUtilities.isLeftToRight(frame);

            int spacing = getHorSpacing();
            int w = getWidth();
            int h = getHeight();

            // assumes all buttons have the same dimensions these dimensions include the borders
            int btnHeight = h - getVerSpacing();
            int btnWidth = btnHeight;

            int x = leftToRight ? w - spacing : 0;
            int y = Math.max(0, ((h - btnHeight) / 2) - 1);

            if (frame.isClosable()) {
                x += leftToRight ? -btnWidth : spacing;
                closeButton.setBounds(x, y, btnWidth, btnHeight);
                if (!leftToRight) {
                    x += btnWidth;
                }
            }

            if (frame.isMaximizable() && !isPalette) {
                x += leftToRight ? -spacing - btnWidth : spacing;
                maxButton.setBounds(x, y, btnWidth, btnHeight);
                if (!leftToRight) {
                    x += btnWidth;
                }
            }

            if (frame.isIconifiable() && !isPalette) {
                x += leftToRight ? -spacing - btnWidth : spacing;
                iconButton.setBounds(x, y, btnWidth, btnHeight);
                if (!leftToRight) {
                    x += btnWidth;
                }
            }

            buttonsWidth = leftToRight ? w - x : x;

            if (customTitlePanel != null) {
                int maxWidth = w - buttonsWidth - spacing - 20;
                Icon icon = frame.getFrameIcon();
                if (icon != null) {
                    maxWidth -= icon.getIconWidth();
                    maxWidth -= spacing;
                }
                int cpw = Math.min(maxWidth, customTitlePanel.getPreferredSize().width);
                int cph = h;
                int cpx = leftToRight ? w - buttonsWidth - cpw : buttonsWidth;
                int cpy = 0;
                customTitlePanel.setBounds(cpx, cpy, cpw, cph);
                buttonsWidth += customTitlePanel.getPreferredSize().width;
            }
        }

        private void layoutMacStyle(Container c) {
            int spacing = getHorSpacing();
            int h = getHeight();

            // assumes all buttons have the same dimensions these dimensions include the borders
            int btnHeight = h - getVerSpacing() - 1;
            int btnWidth = btnHeight;

            int x = 2;
            int y = centerButtons() ? Math.max(0, ((h - btnHeight) / 2)) : 0;

            if (frame.isClosable()) {
                closeButton.setBounds(x, y, btnWidth, btnHeight);
                x += spacing + btnWidth;
            }
            if (frame.isIconifiable() && !isPalette) {
                iconButton.setBounds(x, y, btnWidth, btnHeight);
                x += spacing + btnWidth;
            }
            if (frame.isMaximizable() && !isPalette) {
                maxButton.setBounds(x, y, btnWidth, btnHeight);
                x += spacing + btnWidth;
            }

            buttonsWidth = x;
            
            if (customTitlePanel != null) {
                int cpx = buttonsWidth + 5;
                int cpy = 0;
                int cpw = customTitlePanel.getPreferredSize().width;
                int cph = h;
                customTitlePanel.setBounds(cpx, cpy, cpw, cph);
                buttonsWidth += cpw + 5;
            }
        }
    } // end class BaseTitlePaneLayout
}