/*
    Реализация спецификаций 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 Canvas extends Displayable
{
    public static final int UP     =  1;
    public static final int LEFT   =  2;
    public static final int RIGHT  =  5;
    public static final int DOWN   =  6;
    public static final int FIRE   =  8;
    public static final int GAME_A =  9;
    public static final int GAME_B = 10;
    public static final int GAME_C = 11;
    public static final int GAME_D = 12;
    public static final int KEY_POUND = 35;
    public static final int KEY_STAR  = 42;
    public static final int KEY_NUM0  = 48;
    public static final int KEY_NUM1  = 49;
    public static final int KEY_NUM2  = 50;
    public static final int KEY_NUM3  = 51;
    public static final int KEY_NUM4  = 52;
    public static final int KEY_NUM5  = 53;
    public static final int KEY_NUM6  = 54;
    public static final int KEY_NUM7  = 55;
    public static final int KEY_NUM8  = 56;
    public static final int KEY_NUM9  = 57;

    private boolean focused;

    protected Canvas() {
        super(DeviceManager.getInstance().getSettings().getMIDletProperty("MIDlet-Name"), null, false);
    }

    protected Canvas(String title) {
        super(title, null, false);
    }

    protected Canvas(String title, Ticker ticker, boolean fullScreen) {
        super(title, ticker, fullScreen);
    }

    public void setFullScreenMode(boolean fullScreen) {
        super.setFullScreenMode(fullScreen);
    }

    public int getWidth() {
        return getTotalWidth();
    }

    public int getHeight() {
        return getClientHeight();
    }

    public boolean hasRepeatEvents() {
        return true;
    }

    public boolean hasPointerEvents() {
        return true;
    }

    public boolean hasPointerMotionEvents() {
        return true;
    }

    public boolean isDoubleBuffered() {
        return true;
    }

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

    public int getKeyCode(int gameAction) {
        return DeviceManager.getInstance().getSettings().gameActionToKeyCode(gameAction);
    }

    public String getKeyName(int keyCode) {
        return DeviceManager.getInstance().getSettings().getKeyName(keyCode);
    }

    public final void repaint() {
        requestPaintClient(0, 0, getTotalWidth(), getClientHeight());
    }

    public final void repaint(int clipLeft, int clipTop, int clipWidth, int clipHeight) {
        requestPaintClient(clipLeft, clipTop, clipWidth, clipHeight);
    }

    public final void serviceRepaints() {
        servicePaint();
    }

    protected abstract void paint(Graphics render);

    protected void sizeChanged(int width, int height) {
    }

    protected void showNotify() {
    }

    protected void hideNotify() {
    }

    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) {
    }

    void paint(ScreenGraphics render) {
        paint((Graphics) render);
    }

    void paintBackground(ScreenGraphics render, int width, int height, byte visibleElements, byte drawingElements) {
        super.paintBackground(render, width, height, visibleElements, (byte) (drawingElements & ~CLIENT));
    }

    void paintClient(ScreenGraphics render, int width, int height, int clipLeft, int clipTop, int clipWidth, int clipHeight, Image clipBuffer) {
        if(!isFullScreenMode())
        {
            int translatedX;
            int translatedY;
            render.restricts(translatedX = render.getTranslateX(), translatedY = render.getTranslateY(), width, height);
            render.setStartPoint(translatedX, translatedY);
            render.setClip(0, 0, width, height);
        }
        if(!isMenuOpened()) render.clipRect(clipLeft, clipTop, clipWidth, clipHeight);
        if(clipBuffer != null)
        {
            render.drawImage(clipBuffer, 0, 0, 0);
            return;
        }
        paint(render);
    }

    void onShow() {
        show();
    }

    void onHide() {
        hide();
    }

    boolean onKeyboardEvent(KeyboardEvent event) {
        if(!super.onKeyboardEvent(event)) keyboardEvent(event);
        return true;
    }

    boolean onPointerEvent(PointerEvent event) {
        if(!super.onPointerEvent(event))
        {
            switch(event.getAction())
            {
            case PointerEvent.ACTION_BUTTON_PRESSED:
            case PointerEvent.ACTION_POINTER_PRESSED:
                if(event.getButton() == PointerEvent.BUTTON_MAIN)
                {
                    byte e = getElements();
                    int t = ((e & TICKER) != 0 ? getTickerHeight() : 0) + ((e & TITLE) != 0 ? getTitleHeight() : 0);
                    int w = getTotalWidth();
                    int h = getTotalHeight() - t - ((e & PANEL) != 0 ? getPanelHeight() : 0);
                    int x = event.getX();
                    int y = event.getY() - t;
                    if(x >= 0 && x < w && y >= 0 && y < h)
                    {
                        focused = true;
                        pointerPressed(x, y);
                    }
                }
                break;
            case PointerEvent.ACTION_POINTER_DRAGGED:
                if(focused)
                {
                    byte e = getElements();
                    int t = ((e & TICKER) != 0 ? getTickerHeight() : 0) + ((e & TITLE) != 0 ? getTitleHeight() : 0);
                    int x = event.getX();
                    int y = event.getY() - t;
                    pointerDragged(x, y);
                }
                break;
            case PointerEvent.ACTION_POINTER_RELEASED:
            case PointerEvent.ACTION_BUTTON_RELEASED:
                if(focused && event.getButton() == PointerEvent.BUTTON_MAIN)
                {
                    byte e = getElements();
                    int t = ((e & TICKER) != 0 ? getTickerHeight() : 0) + ((e & TITLE) != 0 ? getTitleHeight() : 0);
                    int x = event.getX();
                    int y = event.getY() - t;
                    focused = false;
                    pointerReleased(x, y);
                }
                break;
            }
        }
        return true;
    }

    void show() {
        showNotify();
    }

    void hide() {
        hideNotify();
    }

    void keyboardEvent(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;
        }
    }
}
