package com.uvigo.mhp.looks;

import java.awt.*;
import java.util.*;
import org.dvb.ui.*;
import org.havi.ui.*;

public class HTextLook1 extends HTextLook
{
    private int labelAreaHeight, labelAreaWidth;
    
    private static final String LINE_SEPARATOR = "\n";
    private int rowHeight, rowAscent;
    private int[] rowWidth;
    private int rowCount;
    private String[] row;
    
    public HTextLook1()
    {
        rowCount = 0;
        labelAreaHeight = 0;
        labelAreaWidth = 0;
    }
    
    public synchronized Dimension getPreferredSize(HVisible visible)
    {
        initialize(visible.getTextContent(HState.NORMAL_STATE));
        calculatePreferredDimensions(visible);
        return new Dimension(labelAreaWidth, labelAreaHeight);
    }
    
    public synchronized Dimension getMinimumSize(HVisible visible)
    {
        return getPreferredSize(visible);
    }
    
    protected synchronized void calculatePreferredDimensions(HVisible visible)
    {
        Font f = visible.getFont();
        FontMetrics fm = (f != null) ? visible.getFontMetrics(f) : null;
        if (fm != null)
        {
            rowHeight = fm.getHeight();
            rowAscent = fm.getAscent();
        }
        
        labelAreaHeight = 0;
        labelAreaWidth = 0;
        if (fm != null && rowCount > 0)
        {
            for (int i = 0; i < rowCount; i++)
            {
                rowWidth[i] = fm.stringWidth(row[i]);
                if (rowWidth[i] > labelAreaWidth)
                    labelAreaWidth = rowWidth[i];
            }
            labelAreaHeight=rowHeight * rowCount;
        }
    }
    
    public void showLook(Graphics g, HVisible visible, int state)
    {
        if (g instanceof DVBGraphics)
        {
            DVBGraphics g2=(DVBGraphics) g;
            DVBAlphaComposite a=DVBAlphaComposite.getInstance(DVBAlphaComposite.SRC_OVER);
            try
            {
                g2.setDVBComposite(a);
            }
            catch(Exception e)
            {
                System.out.println("No se puede aplicar la regla de composici�n");
            }
        }
        
        // Inicializamos el contenido a representar a partir del estado del HVisible
        initialize(visible.getTextContent(state));
        calculatePreferredDimensions(visible);
        
        if (visible.getBackgroundMode()==HVisible.BACKGROUND_FILL)
        {
            g.setColor(visible.getBackground());
            g.fillRect(0,0,visible.getSize().width,visible.getSize().height);
        }
        g.setColor(visible.getForeground());
        displayLabel(g, visible);
    }
    
    protected synchronized void initialize(String label)
    {
        if (label==null) label="";
        
        String lbl = processEscapeSequences(label);
        StringTokenizer t = new StringTokenizer(lbl, LINE_SEPARATOR);
        rowCount = t.countTokens();
        row = new String[rowCount];
        rowWidth = new int[rowCount];
        for (int i = 0; i < rowCount; i++)
            row[i] = t.nextToken();
    }
    
    protected void displayLabel(Graphics g, HVisible visible)
    {
        int x,y;

        if (rowCount < 1)
            return;

        int horizontalAlignment=visible.getHorizontalAlignment();
        int verticalAlignment=visible.getVerticalAlignment();
        
        switch (horizontalAlignment)
        {
            case HVisible.HALIGN_CENTER:
                x = (visible.getSize().width - labelAreaWidth) / 2;
                break;
            case HVisible.HALIGN_RIGHT:
                x = visible.getSize().width - labelAreaWidth;
                break;
            default:
                x = 2;
                break;
        }
        
        switch (verticalAlignment)
        {
            case HVisible.VALIGN_CENTER:
                y = (visible.getSize().height - labelAreaHeight) / 2;
                break;
            case HVisible.VALIGN_BOTTOM:
                y = visible.getSize().height - labelAreaHeight;
                break;
            default:
                y = 0;
                break;
        }
        
        y += rowAscent;
        for (int i=0; i<rowCount; i++, y+=rowHeight)
        {
            int adjX = x;
            switch (horizontalAlignment)
            {
                case HVisible.HALIGN_RIGHT:
                    adjX += labelAreaWidth - rowWidth[i];
                    break;
                case HVisible.HALIGN_CENTER:
                    adjX += (labelAreaWidth - rowWidth[i]) / 2;
                    break;
            }
            g.drawString(row[i], adjX, y);
        }
    }
    
    protected String processEscapeSequences(String in)
    {
        StringBuffer out = new StringBuffer(in.length());
        int j = 0;
        for (int i = 0; i < in.length(); i++, j++)
        {
            switch (in.charAt(i))
            {
                case '\\':
                    switch (in.charAt(i + 1))
                    {
                        case 'n':
                            out.insert(j, '\n');
                            break;
                        case 't':
                            out.insert(j, '\t');
                            break;
                        case 'b':
                            out.insert(j, '\b');
                            break;
                        case 'r':
                            out.insert(j, '\r');
                            break;
                        case 'f':
                            out.insert(j, '\f');
                            break;
                        case '\\':
                            out.insert(j, '\\');
                            break;
                        case '\'':
                            out.insert(j, '\'');
                            break;
                        case '\"':
                            out.insert(j, '\"');
                            break;
                        default:
                            if (Character.isDigit(in.charAt(i + 1)))
                            {
                                String octStr = in.substring(i + 1, i + 4);
                                int octValue = Integer.parseInt(octStr);
                                out.insert(j, Character.forDigit(octValue, 8));
                                i += 2; // salta 2 caracteres por el numero octal
                            }
                            else
                                return null;
                            break;
                    }
                    i++; // salta un caracter mas por la barra invertida
                    break;
                default:
                    out.insert(j, in.charAt(i)); // no hay interpretacion especial
                    break;
            }
        }
        out.setLength(j);
        return out.toString();
    }
}