/*
 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.apple.laf;

import java.awt.*;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.plaf.UIResource;
import javax.swing.text.JTextComponent;

import apple.laf.*;
import apple.laf.JRSUIConstants.*;

import com.apple.laf.AquaUtilControlSize.*;

public abstract class AquaBorder implements Border, UIResource {
    protected final AquaPainter<? extends JRSUIState> painter;
    protected final SizeDescriptor sizeDescriptor;
    protected SizeVariant sizeVariant;

    protected AquaBorder(final SizeDescriptor sizeDescriptor) {
        this.sizeDescriptor = sizeDescriptor;
        this.sizeVariant = sizeDescriptor.get(Size.REGULAR);
        this.painter = createPainter();
    }

    protected AquaPainter<? extends JRSUIState> createPainter() {
        final AquaPainter<JRSUIState> painter = AquaPainter.create(JRSUIState.getInstance());
        painter.state.set(AlignmentVertical.CENTER);
        painter.state.set(AlignmentHorizontal.CENTER);
        return painter;
    }

    protected AquaBorder(final AquaBorder other) {
        this.sizeDescriptor = other.sizeDescriptor;
        this.sizeVariant = other.sizeVariant;
        this.painter = AquaPainter.create(other.painter.state.derive());
        painter.state.set(AlignmentVertical.CENTER);
        painter.state.set(AlignmentHorizontal.CENTER);
    }

    protected void setSize(final Size size) {
        sizeVariant = sizeDescriptor.get(size);
        painter.state.set(size);
    }

    @Override
    public Insets getBorderInsets(final Component c) {
        return (Insets) sizeVariant.margins.clone();
    }

    protected AquaBorder deriveBorderForSize(final Size size) {
        try {
            final Class<? extends AquaBorder> clazz = getClass();
            final AquaBorder border = clazz.getConstructor(new Class[] { clazz }).newInstance(new Object[] { this });
            border.setSize(size);
            return border;
        } catch (final Throwable e) {
            return null;
        }
    }

    public static void repaintBorder(final JComponent c) {
        JComponent borderedComponent = c;
        Border border = c.getBorder();
        if (border == null) {
            // See if it's inside a JScrollpane or something
            final Container p = c.getParent();
            if (p instanceof JViewport) {
                borderedComponent = (JComponent)p.getParent();
                if (borderedComponent != null) border = borderedComponent.getBorder();
            }
        }

        // If we really don't have a border, then bail
        // It might be a compound border with a ThemeBorder inside
        // The check for that case is tricky, so we just go ahead and repaint any border
        if (border == null || borderedComponent == null) return;

        final int width = borderedComponent.getWidth();
        final int height = borderedComponent.getHeight();
        final Insets i = borderedComponent.getInsets();

        borderedComponent.repaint(0, 0, width, i.top); // Top edge
        borderedComponent.repaint(0, 0, i.left, height); // Left edge
        borderedComponent.repaint(0, height - i.bottom, width, i.bottom); // Bottom edge
        borderedComponent.repaint(width - i.right, 0, i.right, height); // Right edge
    }

    // The JScrollPane doesn't let us know if its viewport view has focus
    protected boolean isFocused(final Component c) {
        // Being really paranoid in case this Component isn't a Swing component
        Component focusable = c;

        if (c instanceof JScrollPane) {
            final JViewport vp = ((JScrollPane)c).getViewport();
            if (vp != null) {
                focusable = vp.getView();
                // Lists, Tables & Trees get focus rings, TextAreas don't (JBuilder puts TextField border on TextAreas)
                if (focusable instanceof JTextComponent) return false;
            }
        } else if (focusable instanceof JTextComponent) {
            // non-editable text areas don't draw the focus ring
            if (!((javax.swing.text.JTextComponent)focusable).isEditable()) return false;
        }

        return (focusable != null && focusable instanceof JComponent && ((JComponent)focusable).hasFocus());
    }

    @Override
    public boolean isBorderOpaque() { return false; }

    @Override
    public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int w, final int h) {
        painter.paint(g, c, x, y, w, h);
    }

    static class Default extends AquaBorder {
        Default() { super(new SizeDescriptor(new SizeVariant())); }
    }
}
