/*
 * Copyright (c) 2011, 2016, 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 sun.lwawt.macosx;

import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.peer.MenuItemPeer;
import java.awt.peer.MenuPeer;

public class CMenu extends CMenuItem implements MenuPeer {

    public CMenu(Menu target) {
        super(target);
    }

    // This way we avoiding invocation of the setters twice
    @Override
    protected final void initialize(MenuItem target) {
        setLabel(target.getLabel());
        setEnabled(target.isEnabled());
    }

    @Override
    public final void setEnabled(final boolean b) {
        super.setEnabled(b);
        final Menu target = (Menu) getTarget();
        final int count = target.getItemCount();
        for (int i = 0; i < count; ++i) {
            MenuItem item = target.getItem(i);
            MenuItemPeer p = (MenuItemPeer) LWCToolkit.targetToPeer(item);
            if (p != null) {
                p.setEnabled(b && item.isEnabled());
            }
        }
    }

    @Override
    long createModel() {
        CMenuComponent parent = (CMenuComponent)
            LWCToolkit.targetToPeer(getTarget().getParent());

        if (parent instanceof CMenu) {
            return parent.executeGet(this::nativeCreateSubMenu);
        }
        if (parent instanceof CMenuBar) {
            MenuBar parentContainer = (MenuBar)getTarget().getParent();
            boolean isHelpMenu = parentContainer.getHelpMenu() == getTarget();
            int insertionLocation = ((CMenuBar)parent).getNextInsertionIndex();
            return parent.executeGet(ptr -> nativeCreateMenu(ptr, isHelpMenu,
                                                             insertionLocation));
        }
        throw new InternalError("Parent must be CMenu or CMenuBar");
    }

    @Override
    public final void addItem(MenuItem item) {
        // Nothing to do here -- we added it when we created the
        // menu item's peer.
    }

    @Override
    public final void delItem(final int index) {
        execute(ptr -> nativeDeleteItem(ptr, index));
    }

    @Override
    public final void setLabel(final String label) {
        execute(ptr->nativeSetMenuTitle(ptr, label));
        super.setLabel(label);
    }

    // Note that addSeparator is never called directly from java.awt.Menu,
    // though it is required in the MenuPeer interface.
    @Override
    public final void addSeparator() {
        execute(this::nativeAddSeparator);
    }

    // Used by ScreenMenuBar to get to the native menu for event handling.
    public final long getNativeMenu() {
        return executeGet(this::nativeGetNSMenu);
    }

    private native long nativeCreateMenu(long parentMenuPtr,
                                         boolean isHelpMenu,
                                         int insertionLocation);
    private native long nativeCreateSubMenu(long parentMenuPtr);
    private native void nativeSetMenuTitle(long menuPtr, String title);
    private native void nativeAddSeparator(long menuPtr);
    private native void nativeDeleteItem(long menuPtr, int index);

    // Returns a retained NSMenu object! We have to explicitly
    // release at some point!
    private native long nativeGetNSMenu(long menuPtr);
}
