/*
    Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
    и других спецификаций для функционирования компактных приложений на языке
    Java (мидлетов) в среде программного обеспечения Малик Эмулятор.

    Copyright © 2016–2017, 2019–2022 Малик Разработчик

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
*/

package javax.microedition.lcdui;

import malik.emulator.application.*;
import malik.emulator.microedition.*;

public abstract class CustomItem extends Item
{
    protected static final int NONE                = 0x00;
    protected static final int TRAVERSE_HORIZONTAL = 0x01;
    protected static final int TRAVERSE_VERTICAL   = 0x02;
    protected static final int KEY_PRESS           = 0x04;
    protected static final int KEY_RELEASE         = 0x08;
    protected static final int KEY_REPEAT          = 0x10;
    protected static final int POINTER_PRESS       = 0x20;
    protected static final int POINTER_RELEASE     = 0x40;
    protected static final int POINTER_DRAG        = 0x80;

    private boolean focused;
    private int contentWidth;
    private int contentHeight;

    protected CustomItem(String label) {
        super(label);
    }

    public int getGameAction(int keyCode) {
        return DeviceManager.getInstance().getSettings().keyCodeToGameAction(keyCode);
    }

    protected abstract void paint(Graphics render, int contentWidth, int contentHeight);

    protected abstract int getMinContentWidth();

    protected abstract int getMinContentHeight();

    protected abstract int getPrefContentWidth(int contentHeight);

    protected abstract int getPrefContentHeight(int contentWidth);

    protected void showNotify() {
    }

    protected void hideNotify() {
    }

    protected void sizeChanged(int contentWidth, int contentHeight) {
    }

    protected void keyPressed(int keyCode) {
    }

    protected void keyRepeated(int keyCode) {
    }

    protected void keyReleased(int keyCode) {
    }

    protected void pointerPressed(int x, int y) {
    }

    protected void pointerDragged(int x, int y) {
    }

    protected void pointerReleased(int x, int y) {
    }

    protected void traverseOut() {
    }

    protected boolean traverse(int direction, int viewportWidth, int viewportHeight, int[] visibleRectangle) {
        return false;
    }

    protected final void invalidate() {
        requestInvalidate();
    }

    protected final void repaint() {
        requestPaint();
    }

    protected final void repaint(int clipLeft, int clipTop, int clipWidth, int clipHeight) {
        requestPaint();
    }

    protected final int getInteractionModes() {
        return DeviceManager.getInstance().getSettings().isKeyRepeatedEvent() ? 0xff : 0xff & ~KEY_REPEAT;
    }

    void onShow() {
        try
        {
            showNotify();
        }
        catch(RuntimeException e)
        {
            e.printRealStackTrace();
        }
    }

    void onHide() {
        try
        {
            hideNotify();
        }
        catch(RuntimeException e)
        {
            e.printRealStackTrace();
        }
    }

    void onSizeChanged(int contentWidth, int contentHeight) {
        try
        {
            sizeChanged(this.contentWidth = contentWidth, this.contentHeight = contentHeight);
        }
        catch(RuntimeException e)
        {
            e.printRealStackTrace();
        }
    }

    void onKeyboardEvent(KeyboardEvent event) {
        int keyCode;
        DeviceSettings settings = DeviceManager.getInstance().getSettings();
        switch(event.getAction())
        {
        case KeyboardEvent.ACTION_KEY_PRESSED:
            if((keyCode = settings.getKeyCode(event.getKey())) != 0) keyPressed(keyCode);
            break;
        case KeyboardEvent.ACTION_KEY_REPEATED:
            if(settings.isKeyRepeatedEvent() && (keyCode = settings.getKeyCode(event.getKey())) != 0) keyRepeated(keyCode);
            break;
        case KeyboardEvent.ACTION_KEY_RELEASED:
            if((keyCode = settings.getKeyCode(event.getKey())) != 0) keyReleased(keyCode);
            break;
        }
    }

    void onPointerEvent(PointerEvent event) {
        switch(event.getAction())
        {
        case PointerEvent.ACTION_BUTTON_PRESSED:
        case PointerEvent.ACTION_POINTER_PRESSED:
            if(event.getButton() == PointerEvent.BUTTON_MAIN)
            {
                int x = event.getX();
                int y = event.getY();
                int w = contentWidth;
                int h = contentHeight;
                if(x >= 0 && x < w && y >= 0 && y < h)
                {
                    focused = true;
                    pointerPressed(x, y);
                }
            }
            break;
        case PointerEvent.ACTION_POINTER_DRAGGED:
            if(focused) pointerDragged(event.getX(), event.getY());
            break;
        case PointerEvent.ACTION_POINTER_RELEASED:
        case PointerEvent.ACTION_BUTTON_RELEASED:
            if(focused && event.getButton() == PointerEvent.BUTTON_MAIN)
            {
                focused = false;
                pointerReleased(event.getX(), event.getY());
            }
            break;
        }
    }

    void onFocusLost() {
        try
        {
            traverseOut();
        }
        catch(RuntimeException e)
        {
            e.printRealStackTrace();
        }
    }

    boolean onFocusMove(int direction, int viewportWidth, int viewportHeight, int[] visibleRectangle) {
        boolean result = false;
        try
        {
            if(result = traverse(direction, viewportWidth, viewportHeight, visibleRectangle))
            {
                int w;
                int h;
                if((w = visibleRectangle[2]) < 0) w = 0;
                if((h = visibleRectangle[3]) < 0) h = 0;
                if(w > viewportWidth) w = viewportWidth;
                if(h > viewportHeight) h = viewportHeight;
                visibleRectangle[2] = w;
                visibleRectangle[3] = h;
            }
        }
        catch(RuntimeException e)
        {
            e.printRealStackTrace();
        }
        return result;
    }

    int getDefaultLayout() {
        return LAYOUT_EXPAND;
    }

    int getMinimumContentWidth() {
        int result = 0;
        try
        {
            result = getMinContentWidth();
        }
        catch(RuntimeException e)
        {
            e.printRealStackTrace();
        }
        return result < 0 ? 0 : result;
    }

    int getMinimumContentHeight() {
        int result = 0;
        try
        {
            result = getMinContentHeight();
        }
        catch(RuntimeException e)
        {
            e.printRealStackTrace();
        }
        return result < 0 ? 0 : result;
    }

    int getPreferredContentWidth(int contentHeight) {
        int result = 0;
        try
        {
            result = getPrefContentWidth(contentHeight);
        }
        catch(RuntimeException e)
        {
            e.printRealStackTrace();
        }
        return result < 0 ? 0 : result;
    }

    int getPreferredContentHeight(int contentWidth) {
        int result = 0;
        try
        {
            result = getPrefContentHeight(contentWidth);
        }
        catch(RuntimeException e)
        {
            e.printRealStackTrace();
        }
        return result < 0 ? 0 : result;
    }
}
