/*
 * Copyright (C) 2012 www.amsoft.cn
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.ab.view.sample;


import java.util.ArrayList;
import java.util.List;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint.FontMetrics;
import android.text.Layout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.TextView;

// TODO: Auto-generated Javadoc

/**
 * © 2012 amsoft.cn
 * 名称：AbTextView.java 
 * 描述：中英混合乱换行问题 .
 *
 * @author 还如一梦中
 * @version v1.0
 * @date：2013-05-17 下午6:46:29
 */
public class AbTextView extends TextView {
    
    /** padding. */
    private float leftPadding = 0;
    
    /** The top padding. */
    private float topPadding = 0;
    
    /** The right padding. */
    private float rightPadding = 0;
    
    /** The bottom padding. */
    private float bottomPadding = 0;
    
    /** The line spacing. */
    private float lineSpacing = 0;
    
    /** 最大行数. */
    private int maxLines = 1;
    
    /** 文字大小. */
    private float textSize = 14;
    
    /** 文字颜色. */
    private int textColor = Color.WHITE;
    
    /** TextPaint. */
    private TextPaint mTextPaint = null;

    /**
     * Instantiates a new ab text view.
     *
     * @param context the context
     * @param attrs the attrs
     */
    public AbTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mTextPaint = this.getPaint();
        mTextPaint.setColor(textColor);
        mTextPaint.setTextSize(textSize);
    }

    /* (non-Javadoc)
     * @see android.widget.TextView#onDraw(android.graphics.Canvas)
     */
    @Override
    protected void onDraw(Canvas canvas) {
        // 清屏幕
        canvas.drawColor(Color.TRANSPARENT);
        drawText(canvas, this.getText().toString(), this.getWidth(), this.getPaint());
    }

    /**
     * Sets the padding.
     *
     * @param left the left
     * @param top the top
     * @param right the right
     * @param bottom the bottom
     */
    @Override
    public void setPadding(int left,int top,int right,int bottom){
        leftPadding = left;
        topPadding = top;
        rightPadding = right;
        bottomPadding = bottom;
        this.invalidate();
    }


    /**
     * Sub string length.
     *
     * @param str the str
     * @param maxPix the max pix
     * @param paint the paint
     * @return the int
     */
    public int subStringLength(String str, int maxPix, TextPaint paint) {
        if (TextUtils.isEmpty(str)) {
            return 0;
        }
        int currentIndex = 0;
        for (int i = 0; i < str.length(); i++) {
            // 获取一个字符
            String temp = str.substring(0, i + 1);
            float valueLength = paint.measureText(temp)+leftPadding+rightPadding;
            if (valueLength > maxPix) {
                currentIndex = i - 1;
                break;
            } else if (valueLength == maxPix) {
                currentIndex = i;
                break;
            }
        }
        // 短于最大像素返回最后一个字符位置
        if (currentIndex == 0) {
            currentIndex = str.length() - 1;
        }
        return currentIndex;
    }

    /**
     * Gets the string width.
     *
     * @param str the str
     * @param paint the paint
     * @return the string width
     */
    public float getStringWidth(String str, TextPaint paint) {
        float strWidth = paint.measureText(str);
        return strWidth;
    }

    /**
     * Gets the desired width.
     *
     * @param str the str
     * @param paint the paint
     * @return the desired width
     */
    public float getDesiredWidth(String str, TextPaint paint) {
        float strWidth = Layout.getDesiredWidth(str, paint);
        return strWidth;
    }

    /**
     * Gets the draw row str.
     *
     * @param text the text
     * @param maxWPix the max w pix
     * @param paint the paint
     * @return the draw row str
     */
    public List<String> getDrawRowStr(String text, int maxWPix,
            TextPaint paint) {
        String[] texts = null;
        if (text.indexOf("\n") != -1) {
            texts = text.split("\n");
        } else {
            texts = new String[1];
            texts[0] = text;
        }
        // 共多少行
        List<String> mStrList = new ArrayList<String>();

        for (int i = 0; i < texts.length; i++) {
            String textLine = texts[i];
            // 计算这个文本显示为几行
            while (true) {
                // 可容纳的最后一个字的位置
                int endIndex = subStringLength(textLine, maxWPix, paint);
                if (endIndex <= 0) {
                    mStrList.add(textLine);
                } else {
                    if (endIndex == textLine.length() - 1) {
                        mStrList.add(textLine);
                    } else {
                        mStrList.add(textLine.substring(0, endIndex + 1));
                    }

                }
                // 获取剩下的
                if (textLine.length() > endIndex + 1) {
                    // 还有剩下的
                    textLine = textLine.substring(endIndex + 1);
                } else {
                    break;
                }
            }
        }

        return mStrList;
    }

    /**
     * Gets the draw row count.
     *
     * @param text the text
     * @param maxWPix the max w pix
     * @param paint the paint
     * @return the draw row count
     */
    public int getDrawRowCount(String text, int maxWPix, TextPaint paint) {
        String[] texts = null;
        if (text.indexOf("\n") != -1) {
            texts = text.split("\n");
        } else {
            texts = new String[1];
            texts[0] = text;
        }
        // 共多少行
        List<String> mStrList = new ArrayList<String>();

        for (int i = 0; i < texts.length; i++) {
            String textLine = texts[i];
            // 计算这个文本显示为几行
            while (true) {
                // 可容纳的最后一个字的位置
                int endIndex = subStringLength(textLine, maxWPix, paint);
                if (endIndex <= 0) {
                    mStrList.add(textLine);
                } else {
                    if (endIndex == textLine.length() - 1) {
                        mStrList.add(textLine);
                    } else {
                        mStrList.add(textLine.substring(0, endIndex + 1));
                    }

                }
                // 获取剩下的
                if (textLine.length() > endIndex + 1) {
                    // 还有剩下的
                    textLine = textLine.substring(endIndex + 1);
                } else {
                    break;
                }
            }
        }

        return mStrList.size();
    }

    /**
     * Draw text.
     *
     * @param canvas the canvas
     * @param text the text
     * @param maxWPix the max w pix
     * @param paint the paint
     * @return the int
     */
    public int drawText(Canvas canvas, String text, int maxWPix,
            TextPaint paint) {
        if (TextUtils.isEmpty(text)) {
            return 1;
        }
        // 需要根据文字长度控制换行
        // 测量文字的长度
        List<String> mStrList = getDrawRowStr(text, maxWPix, paint);

        FontMetrics fm = paint.getFontMetrics();
        int hSize = (int)Math.ceil(fm.descent - fm.ascent);

        for (int i = 0; i < mStrList.size(); i++) {
            // 计算坐标
            float x = leftPadding;
            float y = topPadding+hSize/2+i*(hSize+lineSpacing)+bottomPadding;
            String textLine = mStrList.get(i);
            if(i < maxLines){
                canvas.drawText(textLine, x, y, paint);
            }
        }
        return mStrList.size();
    }


    /**
     * Gets the max lines.
     *
     * @return the max lines
     */
    @SuppressLint("Override")
    public int getMaxLines(){
        return maxLines;
    }

    /* (non-Javadoc)
     * @see android.widget.TextView#setMaxLines(int)
     */
    @Override
    public void setMaxLines(int maxLines){
        this.maxLines = maxLines;
        this.invalidate();
    }
    
    /**
     * Gets the line spacing.
     *
     * @return the line spacing
     */
    public float getLineSpacing(){
        return lineSpacing;
    }

    /**
     * Sets the line spacing.
     *
     * @param lineSpacing the new line spacing
     */
    public void setLineSpacing(float lineSpacing){
        this.lineSpacing = lineSpacing;
    }

    /* (non-Javadoc)
     * @see android.widget.TextView#setTextSize(float)
     */
    @Override
    public void setTextSize(float size) {
        this.textSize = size;
        Context c = getContext();
        Resources r;

        if (c == null)
            r = Resources.getSystem();
        else
            r = c.getResources();

        setRawTextSize(TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_SP, size, r.getDisplayMetrics()));
    }
    
    
    /**
     * Sets the raw text size.
     *
     * @param size the new raw text size
     */
    private void setRawTextSize(float size) {
        if (size != mTextPaint.getTextSize()) {
            mTextPaint.setTextSize(size);
            this.invalidate();
        }
    }

    /* (non-Javadoc)
     * @see android.widget.TextView#getTextSize()
     */
    public float getTextSize(){
        return textSize;
    }

    /**
     * Gets the text color.
     *
     * @return the text color
     */
    public int getTextColor(){
        return textColor;
    }

    /* (non-Javadoc)
     * @see android.widget.TextView#setTextColor(int)
     */
    @Override
    public void setTextColor(int textColor){
        this.textColor = textColor;
        mTextPaint.setColor(textColor);
        this.invalidate();
    }
    
    
}
