import java.io.DataInputStream;
import java.io.IOException;
import java.util.Vector;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
/**
 *
 * @author user
 */
public class DrawText {
    
    private boolean wAlpha;
    private int color, tY, hText, scrolling;
    private int[] clip, back_clip;
    private float dist;
    private String[] fText;
    private Image[] font;
    
    /*
     * Конструктор класса, инициализирует основные компоненты
     */
    public DrawText() {
        clip = new int[4];
        back_clip = new int[4];
        wAlpha = false;
    }

    /*
     * Загружает шрифт из картинки iFont
     */
    public void loadFont(Image iFont) {
        int[][] pFont = getFontPoints();
        font = new Image[pFont.length];
        for(int i=0; i<font.length; i++) {
            font[i] = Image.createImage(iFont, pFont[i][0], 0, pFont[i][1], 14, 0);
        }
        pFont = null;
        iFont = null;
    }
    
    /*
     * Получает все данные о шрифте
     */
    private int[][] getFontPoints() {
        DataInputStream dis = new DataInputStream(getClass().getResourceAsStream("/resources/"+Localization.getLocaleAsString()+"_font.dat"));
        String sPoints = "";
        try {
            int ch;
            while((ch = dis.readUnsignedByte()) != -1) {
                sPoints+=(char)ch;
            }
        } catch (IOException ex) {}
        dis = null;
        Vector vector = new Vector();
        int p1 = 0, p2;
        while((p2 = sPoints.indexOf("\r\n", p1)) != -1) {
            vector.addElement(sPoints.substring(p1, p2));
            p1 = p2+2;
        }
        sPoints = null;
        int[][] points = new int[vector.size()][2];
        for(int i=0; i<points.length; i++) {
            String point = (String)vector.elementAt(i);
            int p = point.indexOf('-');
            points[i][0] = Integer.parseInt(point.substring(0, p));
            points[i][1] = Integer.parseInt(point.substring(p+1));
            point = null;
        }
        vector = null;
        return points;
    }
    
    /*
     * Устанавливает цвет
     */
    public void setColor(int color) {
        this.color = color;
    }
    
    /*
     * Устанавливает возможность установки разной прозрачности шрифта
     */
    public void setColorWithAlpha(boolean b) {
        wAlpha = b;
    }
    
    /*
     * Рисует строку string, по координатам x и y
     */
    public void drawString(Graphics g, int x, int y, String string) {
        for(int i=0; i<string.length(); i++) {
            int charCode = checkCharCode(string.charAt(i));
            int[] argb = new int[font[charCode].getWidth()*font[charCode].getHeight()];
            font[charCode].getRGB(argb, 0, font[charCode].getWidth(), 0, 0, font[charCode].getWidth(), font[charCode].getHeight());
            for(int j=0; j<argb.length; j++) {
                if(wAlpha) {
                    argb[j] = ((int)((float)((argb[j] >> 24) & 0xff)/255f*(float)((color >> 24) & 0xff)) << 24) | 0xffffff;
                } else {
                    argb[j] = (((argb[j] >> 24) & 0xff) << 24) | color;
                }
            }
            g.drawRGB(argb, 0, font[charCode].getWidth(), x, y, font[charCode].getWidth(), font[charCode].getHeight(), true);
            argb = null;
            x+=font[charCode].getWidth()+1;
        }
    }
    
    /*
     * Проверяет корректность символа для отображения
     */
    private int checkCharCode(int charCode) {
        if(charCode >= 32 && charCode <= 126) charCode-=32;
        if(charCode >= 192 && charCode <= 255) charCode-=97;
        if(charCode >= 1040 && charCode <= 1103) charCode-=945;
        return charCode;
    }
    
    /*
     * Возврщает ширину строки
     */
    public int stringWidth(String string) {
        int width = 0;
        for(int i=0; i<string.length(); i++) {
            width+=font[checkCharCode(string.charAt(i))].getWidth()+(i < string.length()-1 ? 1 : 0);
        }
        return width;
    }
    
    /*
     * Создает окно x, y, width, height и отображает в нем text
     */
    public void setText(String text, int x, int y, int width, int height) {
        clip[0] = x;
        clip[1] = y;
        clip[2] = width;
        clip[3] = height;
        if(tY != 0) tY = 0;
        format(text, width);
    }
    
    /*
     * Создает окно x, y, width с произвольной высотой (полная высотка форматированного текста), и отображает text. Возвращает height текста
     */
    public int setText(String text, int x, int y, int width) {
        clip[0] = x;
        clip[1] = y;
        clip[2] = width;
        if(tY != 0) tY = 0;
        format(text, width);
        return (clip[3] = hText);
    }
    
    /*
     * Форматирует text с в ширину - width
     */
    private void format(String text, int width) {
        if(fText != null) fText = null;
        Vector pVector = new Vector();
        int p1 = 0, p2;
        while((p2 = text.indexOf('\n', p1)) != -1) {
            pVector.addElement(substring(text, p1, p2));
            p1 = p2+1;
        }
        if(p1 < text.length()-1) pVector.addElement(substring(text, p1));
        Vector fVector = new Vector();
        for(int i=0; i<pVector.size(); i++) {
            String line = ((String)pVector.elementAt(i));
            if(line.length() > 0) {
                if(line.charAt(line.length()-1) != ' ') line+=' ';
                int p = p1 = 0;
                while((p2 = line.indexOf(' ', p1)) != -1) {
                    if(stringWidth(substring(line, p, p2)) > width) {
                        fVector.addElement(substring(line, p, p1));
                        p = p1;
                    }
                    p1 = p2+1;
                }
                if(p < line.length()-1) fVector.addElement(substring(line, p));
            } else {
                fVector.addElement(line);
            }
            line = null;
        }
        pVector = null;
        hText = fVector.size()*14;
        fText = new String[fVector.size()];
        for(int i=0; i<fVector.size(); i++) {
            fText[i] = (String)fVector.elementAt(i);
        }
        fVector = null;
    }
    
    /*
     * Возвращает форматированный текст в виде массива
     */
    public String[] getArray() {
        return fText;
    }
    
    /*
     * Аналог функции String.substring(int)
     */
    private String substring(String string, int p) {
        return string.substring(p);
    }
    
    /*
     * Аналог функции String.substring(int, int)
     */
    private String substring(String string, int p1, int p2) {
        return string.substring(p1, p2);
    }
    
    /*
     * Выводит форматированный (уст. функцией setText) текст. Если boolean - false, то не будет создаваться ограничение setClip
     */
    public void drawText(Graphics g, boolean setClip) {
        if(setClip) getClip(g);
        g.setColor(0x000000);
        if(setClip) g.setClip(clip[0], clip[1], clip[2], clip[3]);
        for(int i=0; i<fText.length; i++) {
            if(fText[i].length() > 0) {
                int Y = clip[1]+(hText < clip[3] ? clip[3]/2-hText/2 : tY)+i*14;
                if(Y >= clip[1] && Y < clip[1]+clip[3]) drawString(g, clip[0]+clip[2]/2-stringWidth(fText[i])/2, Y, fText[i]);
            }
        }
        if(setClip) setClip(g);
    }
    
    /*
     * Устанавливает Y координату текста
     */
    public void setY(int i) {
        tY = i;
    }
    
    /*
     * Возвращает Y координату текста
     */
    public int getY() {
        return tY;
    }
    
    /*
     * Возвращает высоту форматированного текста
     */
    public int getHText() {
        return hText;
    }
    
    /*
     * Записывает в массив текущие данные окна setClip
     */
    private void getClip(Graphics g) {
        back_clip[0] = g.getClipX();
        back_clip[1] = g.getClipY();
        back_clip[2] = g.getClipWidth();
        back_clip[3] = g.getClipHeight();
    }
    
    /*
     * Устанавливает из массива данные окна setClip
     */
    private void setClip(Graphics g) {
        g.setClip(back_clip[0], back_clip[1], back_clip[2], back_clip[3]);
    }
    
}
