package com.yidian.shenghuoquan.newscontent.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.text.Layout;
import android.text.NoCopySpan;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.NonNull;

import com.yidian.nightmode.widget.YdTextView;
import com.yidian.shenghuoquan.newscontent.R;

public class ExpandTextView extends YdTextView {
    private static final String TAG = "ExpandTextView";
    private String originText = "";                //原始内容文本
    private int initWidth = 0;                //TextView可展示宽度
    private int mMaxLines = 2;                //TextView最大显示行数
    private SpannableString SPAN_CLOSE = null;       //收起的文本(颜色处理和点击监听)
    private SpannableString SPAN_EXPAND = null;      //展开的文本(颜色处理和点击监听)
    private String TEXT_EXPAND = " 展开";
    private String TEXT_CLOSE = " 收起";
    private int SPAN_COLOR = R.color.video_transparent_50;
    private boolean isClose = true;
 
    private boolean isWidthModify = true;           //用于控件宽高改变时通知重绘的判断，避免循环绘制
    private ExpandClickListener l;

    public ExpandTextView(Context context) {
        super(context);
    }
 
    public ExpandTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
 
    public ExpandTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
 
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        initWidth = getMeasuredWidth();
        if(isWidthModify) {
            notifyRefreshView();
            isWidthModify = false;
        }
    }
 
    /**
     * 初始化"展开"的Span文本，即收起状态的文本尾
     */
    private void initCloseEnd(){
        String content = TEXT_EXPAND;
        SPAN_CLOSE = new SpannableString(content);
        SPAN_CLOSE.setSpan(new NoRefCopySpan() {
            @SuppressLint("ResourceType")
            @Override
            public void updateDrawState(TextPaint ds) {
                ds.setColor(getResources().getColor(SPAN_COLOR));
                ds.setUnderlineText(false);
            }
 
            @Override
            public void onClick(@NonNull View widget) {
                if (l!=null){
                    l.onClick(true);
                }
                ExpandTextView.super.setMaxLines(Integer.MAX_VALUE);
                setExpandText(originText);
            }
 
        }, 0, content.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
    }
 
    /**
     * 初始化"收起"的Span文本，即展开状态的文本尾
     */
    private void initExpandEnd(){
        String content = TEXT_CLOSE;
        SPAN_EXPAND = new SpannableString(content);
        SPAN_EXPAND.setSpan(new NoRefCopySpan() {
            @SuppressLint("ResourceType")
            @Override
            public void updateDrawState(TextPaint ds) {
                ds.setColor(getResources().getColor(SPAN_COLOR));
                ds.setUnderlineText(false);
            }
 
            @Override
            public void onClick(@NonNull View widget) {
                if (l!=null){
                    l.onClick(false);
                }
                ExpandTextView.super.setMaxLines(mMaxLines);
                setCloseText(originText);
            }
 
        }, 0, content.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
    }

 
    /**
     * 设置收起状态时的文本
     */
    private void setCloseText(CharSequence text) {
        if(SPAN_CLOSE == null){
            initCloseEnd();
        }
        boolean appendShowAll = false;//true不需要展开收起功能(文件行数小于或等于最大行)，false需要展开收起功能
        originText = text.toString();
        int maxLines = getMaxLines();
        String workingText = originText;
        if (maxLines != -1) {
            Layout layout = createWorkingLayout(workingText);
            if (layout.getLineCount() > maxLines) {
                //获取一行显示字符个数，然后截取字符串数
                workingText = originText.substring(0, layout.getLineEnd(maxLines - 1)).trim();// 收起状态原始文本截取展示的部分
                String showText = originText.substring(0, layout.getLineEnd(maxLines - 1)).trim() + "..." + SPAN_CLOSE;
                Layout layout2 = createWorkingLayout(showText);
                //对workingText进行-1截取，直到展示行数==最大行数，并且添加SPAN_CLOSE后刚好占满最后一行
                while (layout2.getLineCount() > maxLines) {
                    int lastSpace = workingText.length()-1;
                    if (lastSpace == -1) {
                        break;
                    }
                    workingText = workingText.substring(0, lastSpace);
                    layout2 = createWorkingLayout(workingText + "..." + SPAN_CLOSE);
                }
                appendShowAll = true;
                workingText = workingText + "...";
            }
        }
 
        setText(workingText);
        if (appendShowAll) {
            // 必须使用append，不能在上面使用+连接，否则spannable会无效
            append(SPAN_CLOSE);
            setMovementMethod(LinkMovementMethod.getInstance());
        }
        invalidate();
        post(this::requestLayout);
    }
 
    /**
     * 设置展开状态时的文本
     */
    @SuppressLint("SetTextI18n")
    private void setExpandText(String text) {
        if(SPAN_EXPAND == null){
            initExpandEnd();
        }
        Layout layout1 = createWorkingLayout(text);
        Layout layout2 = createWorkingLayout(text + TEXT_CLOSE);
        // 展示全部原始内容时 如果 TEXT_CLOSE 需要换行才能显示完整，则直接将TEXT_CLOSE展示在下一行
        if(layout2.getLineCount() > layout1.getLineCount()){
            setText(originText + "\n");
        }else{
            setText(originText);
        }
        append(SPAN_EXPAND);
        setMovementMethod(LinkMovementMethod.getInstance());
        invalidate();
        post(this::requestLayout);
    }
 
    /**
     * 返回textview的显示区域的layout，该textview的layout并不会显示出来
     * 只是用其宽度来比较要显示的文字是否过长。
     */
    private Layout createWorkingLayout(String workingText) {

        return new StaticLayout(workingText, getPaint(), initWidth - getPaddingLeft() - getPaddingRight(),
                Layout.Alignment.ALIGN_NORMAL, getLineSpacingMultiplier(), getLineSpacingExtra(), false);
    }
 
    /**
     * sdk>=16，可以通过xml进行配置，但16以下必须用该方法配置
     */
    @Override
    public void setMaxLines(int maxLines) {
        this.mMaxLines = maxLines;
        super.setMaxLines(maxLines);
    }
 
    /**
     * @param originText 待显示的原文本;
     * @param isClose 设置TextView的初始状态是否为收起;
     * 设置文本时，需要调用该方法来代替setText。若直接使用setText方法设置文本，
     * 该控件只会作为普通TextView显示。
     */
    public void setText(String originText, boolean isClose) {
        this.originText = originText;
        this.isClose = isClose;
        isWidthModify = true;
        notifyRefreshView();
    }
 
    /**
     * 修改设置后通知重绘,setText(String originText, Boolean isClose)方法不需要调用
     */
    public void notifyRefreshView() {
        if(isClose) {
            ExpandTextView.super.setMaxLines(mMaxLines);
            setCloseText(originText);
        } else {
            ExpandTextView.super.setMaxLines(Integer.MAX_VALUE);
            setExpandText(originText);
        }
    }
 
    /**
     * @param colorId 展开和收起时，文本尾的Span文本的颜色;
     * 设置展开和收起时文本尾的Span文本的颜色（若不以该方法设置，则默认为R.color.red）。
     */
    public void setLabelTextColor(int colorId) {
        SPAN_COLOR = colorId;
        initExpandEnd();
        initCloseEnd();
    }
 
    /**
     * @param str 收起时，文本尾代表"展开"的Span文本内容;
     * 设置文本尾的"展开"Span文本的内容（若不以该方法设置，则默认为"展开"）。
     */
    public void setExpandLabelText(String str) {
        TEXT_EXPAND = str;
        initExpandEnd();
    }
 
    /**
     * @param str 展开时，文本尾代表"收起"的Span文本内容;
     * 设置文本尾的"收起"Span文本的内容（若不以该方法设置，则默认为"收起"）。
     */
    public void setCLOSELabelText(String str) {
        TEXT_CLOSE = str;
        initCloseEnd();
    }
 
    /**
     * 实现NoCopySpan的原因是，为了防止Span在onSaveInstanceState时被复制保存，导致内存泄漏
     */
    public static class NoRefCopySpan extends ClickableSpan implements NoCopySpan {
 
        @Override
        public void onClick(@NonNull View widget) {
            //等待子类继承
        }
 
        @Override
        public void updateDrawState(TextPaint ds) {
            super.updateDrawState(ds);
        }
 
    }
    public void setOnExpandClickListener(ExpandClickListener listener){
        this.l = listener;
    }
    interface ExpandClickListener{
        void onClick(boolean isExpand);
    }
}