/*
    Реализация спецификаций 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.media.graphics.*;
import malik.emulator.microedition.*;
import malik.emulator.microedition.lcdui.*;
import malik.emulator.util.*;

public class SurfaceTextViewer extends SurfaceScreen
{
    private char[] buffer;
    private String text;
    private Font font;
    private final MultilinedStringBuilder builder;

    public SurfaceTextViewer(String text) {
        this(text, null, null);
    }

    public SurfaceTextViewer(String text, Font font) {
        this(text, font, null);
    }

    public SurfaceTextViewer(String text, Font font, ScrollBarStyle style) {
        super(null, 0, true, style);
        MultilinedStringBuilder builder;
        (builder = new FastMultilinedStringBuilder()).append(text);
        this.text = text;
        this.font = font;
        this.builder = builder;
        correctScrollBarRange(builder);
    }

    public void setFont(Font font) {
        MultilinedStringBuilder builder;
        synchronized(builder = this.builder)
        {
            this.font = font;
            correctScrollBarRange(builder);
            requestPaintAll();
        }
    }

    public void setText(String text) {
        MultilinedStringBuilder builder;
        synchronized(builder = this.builder)
        {
            this.text = text;
            builder.clear();
            builder.append(text);
            correctScrollBarRange(builder);
            requestPaintAll();
        }
    }

    public Font getFont() {
        return font;
    }

    public String getText() {
        return text;
    }

    void paint(ScreenGraphics render) {
        int clipTop = render.getClipY();
        int clipHeight = render.getClipHeight();
        MultilinedStringBuilder builder;
        synchronized(builder = this.builder)
        {
            int len;
            int lhei;
            int line;
            int srow;
            int frow;
            char[] lbuf = buffer;
            Font font = this.font;
            srow = clipTop / (line = font.getHeight());
            frow = (clipTop + clipHeight - 1) / line;
            render.setFont(font);
            render.setColor(RasterCanvas.getSystemColor(0x28));
            lhei = font.getHeight() * (len = builder.lines());
            for(int top = clipHeight < lhei ? srow * line : (clipHeight - lhei) >> 1, index = srow; index <= frow && index < len; top += line, index++)
            {
                int lofs = builder.lineOffset(index);
                int llen = builder.lineLength(index);
                if(lbuf == null || lbuf.length < llen) lbuf = buffer = new char[StringBuilder.optimalCapacity(llen)];
                builder.copy(lofs, lofs + llen, lbuf, 0);
                render.drawChars(lbuf, 0, llen, 0, top, Graphics.LEFT | Graphics.TOP);
            }
        }
    }

    void onSizeChanged(int width, int height) {
        MultilinedStringBuilder builder;
        synchronized(builder = this.builder)
        {
            correctScrollBarRange(builder);
        }
        super.onSizeChanged(width, height);
    }

    void onClientKeyboardEvent(KeyboardEvent event) {
        int key = event.getKey();
        Font font;
        DeviceSettings settings = DeviceManager.getInstance().getSettings();
        switch(event.getAction())
        {
        case KeyboardEvent.ACTION_KEY_PRESSED:
        case KeyboardEvent.ACTION_KEY_REPEATED:
            if(key == settings.getKeyUsedAs(DeviceSettings.DEVICE_KEY_DOWN))
            {
                super.getScrollBar().scroll(+((font = this.font) == null ? Font.getDefaultFont() : font).getHeight());
            }
            else if(key == settings.getKeyUsedAs(DeviceSettings.DEVICE_KEY_UP))
            {
                super.getScrollBar().scroll(-((font = this.font) == null ? Font.getDefaultFont() : font).getHeight());
            }
            break;
        }
    }

    private void correctScrollBarRange(MultilinedStringBuilder builder) {
        Font font;
        if((font = this.font) == null) font = Font.getDefaultFont();
        builder.split(font, super.getWidth());
        super.getScrollBar().setRange(font.getHeight() * builder.lines());
    }
}

final class ChoiceElementViewer extends SurfaceTextViewer implements CommandListener
{
    private static final Command BACK;

    static {
        BACK = new Command("Назад", Command.BACK, 0);
    }

    public ChoiceElementViewer() {
        super(null, null, null);
        super.setCommandListener(this);
        super.addCommand(BACK);
    }

    public void commandAction(Command command, Displayable screen) {
        Display parent;
        if(screen == this && command == BACK && (parent = getParentDisplay()) != null) parent.hideSurfaceScreen();
    }

    void onClientKeyboardEvent(KeyboardEvent event) {
        int key = event.getKey();
        Display parent;
        ScrollBar scroll;
        DeviceSettings settings = DeviceManager.getInstance().getSettings();
        if(
            event.getAction() == KeyboardEvent.ACTION_KEY_RELEASED && key == settings.getKeyUsedAs(DeviceSettings.DEVICE_KEY_POUND) &&
            (scroll = super.getScrollBar()).getRange() <= scroll.getPage() && (parent = getParentDisplay()) != null
        ) parent.hideSurfaceScreen();
        super.onClientKeyboardEvent(event);
    }
}
