/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * 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.android.test.voiceinteraction;

import android.annotation.Nullable;
import android.app.assist.AssistStructure;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import java.util.ArrayList;

public class AssistVisualizer extends View {
    static final String TAG = "AssistVisualizer";

    static class TextEntry {
        final Rect bounds;
        final int parentLeft, parentTop;
        final Matrix matrix;
        final String className;
        final float textSize;
        final int textColor;
        final CharSequence text;
        final int scrollY;
        final int[] lineCharOffsets;
        final int[] lineBaselines;

        TextEntry(AssistStructure.ViewNode node, int parentLeft, int parentTop, Matrix matrix) {
            int left = parentLeft+node.getLeft();
            int top = parentTop+node.getTop();
            bounds = new Rect(left, top, left+node.getWidth(), top+node.getHeight());
            this.parentLeft = parentLeft;
            this.parentTop = parentTop;
            this.matrix = new Matrix(matrix);
            this.className = node.getClassName();
            this.textSize = node.getTextSize();
            this.textColor = node.getTextColor();
            this.text = node.getText() != null ? node.getText() : node.getContentDescription();
            this.scrollY = node.getScrollY();
            this.lineCharOffsets = node.getTextLineCharOffsets();
            this.lineBaselines = node.getTextLineBaselines();
        }
    }

    AssistStructure mAssistStructure;
    final Paint mFramePaint = new Paint();
    final Paint mFrameBaselinePaint = new Paint();
    final Paint mFrameNoTransformPaint = new Paint();
    final ArrayList<Matrix> mMatrixStack = new ArrayList<>();
    final ArrayList<TextEntry> mTextRects = new ArrayList<>();
    final int[] mTmpLocation = new int[2];

    public AssistVisualizer(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        setWillNotDraw(false);
        mFramePaint.setColor(0xffff0000);
        mFramePaint.setStyle(Paint.Style.STROKE);
        mFramePaint.setStrokeWidth(0);
        mFrameBaselinePaint.setColor(0xa0b0b000);
        mFrameBaselinePaint.setStyle(Paint.Style.STROKE);
        mFrameBaselinePaint.setStrokeWidth(0);
        float density = getResources().getDisplayMetrics().density;
        mFramePaint.setShadowLayer(density, density, density, 0xff000000);
        mFrameNoTransformPaint.setColor(0xff0000ff);
        mFrameNoTransformPaint.setStyle(Paint.Style.STROKE);
        mFrameNoTransformPaint.setStrokeWidth(0);
        mFrameNoTransformPaint.setShadowLayer(density, density, density, 0xff000000);
    }

    public void setAssistStructure(AssistStructure as) {
        mAssistStructure = as;
        mTextRects.clear();
        final int N = as.getWindowNodeCount();
        if (N > 0) {
            for (int i=0; i<N; i++) {
                AssistStructure.WindowNode windowNode = as.getWindowNodeAt(i);
                mMatrixStack.clear();
                Matrix matrix = new Matrix();
                matrix.setTranslate(windowNode.getLeft(), windowNode.getTop());
                mMatrixStack.add(matrix);
                buildTextRects(windowNode.getRootViewNode(), 0, windowNode.getLeft(),
                        windowNode.getTop());
            }
        }
        Log.d(TAG, "Building text rects in " + this + ": found " + mTextRects.size());
        invalidate();
    }

    public void logTree() {
        if (mAssistStructure != null) {
            mAssistStructure.dump(true);
        }
    }

    public void logText() {
        final int N = mTextRects.size();
        for (int i=0; i<N; i++) {
            TextEntry te = mTextRects.get(i);
            Log.d(TAG, "View " + te.className + " " + te.bounds.toShortString()
                    + " in " + te.parentLeft + "," + te.parentTop
                    + " matrix=" + te.matrix.toShortString()
                    + " size=" + te.textSize + " color=#" + Integer.toHexString(te.textColor)
                    + ": "
                    + te.text);
            if (te.lineCharOffsets != null && te.lineBaselines != null) {
                final int num = te.lineCharOffsets.length < te.lineBaselines.length
                        ? te.lineCharOffsets.length : te.lineBaselines.length;
                for (int j=0; j<num; j++) {
                    Log.d(TAG, "  Line #" + j + ": offset=" + te.lineCharOffsets[j]
                            + " baseline=" + te.lineBaselines[j]);
                }
            }
        }
    }

    public void clearAssistData() {
        mAssistStructure = null;
        mTextRects.clear();
    }

    void buildTextRects(AssistStructure.ViewNode root, int matrixStackIndex,
            int parentLeft, int parentTop) {
        if (root.getVisibility() != View.VISIBLE) {
            return;
        }
        Matrix parentMatrix = mMatrixStack.get(matrixStackIndex);
        matrixStackIndex++;
        Matrix matrix;
        if (mMatrixStack.size() > matrixStackIndex) {
            matrix = mMatrixStack.get(matrixStackIndex);
            matrix.set(parentMatrix);
        } else {
            matrix = new Matrix(parentMatrix);
            mMatrixStack.add(matrix);
        }
        matrix.preTranslate(root.getLeft(), root.getTop());
        int left = parentLeft + root.getLeft();
        int top = parentTop + root.getTop();
        Matrix transform = root.getTransformation();
        if (transform != null) {
            matrix.preConcat(transform);
        }
        if (root.getText() != null || root.getContentDescription() != null) {
            TextEntry te = new TextEntry(root, parentLeft, parentTop, matrix);
            mTextRects.add(te);
        }
        final int N = root.getChildCount();
        if (N > 0) {
            left -= root.getScrollX();
            top -= root.getScrollY();
            matrix.preTranslate(-root.getScrollX(), -root.getScrollY());
            for (int i=0; i<N; i++) {
                AssistStructure.ViewNode child = root.getChildAt(i);
                buildTextRects(child, matrixStackIndex, left, top);
            }
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        getLocationOnScreen(mTmpLocation);
        final int N = mTextRects.size();
        Log.d(TAG, "Drawing text rects in " + this + ": found " + mTextRects.size());
        for (int i=0; i<N; i++) {
            TextEntry te = mTextRects.get(i);
            canvas.drawRect(te.bounds.left - mTmpLocation[0], te.bounds.top - mTmpLocation[1],
                    te.bounds.right - mTmpLocation[0], te.bounds.bottom - mTmpLocation[1],
                    mFrameNoTransformPaint);
        }
        for (int i=0; i<N; i++) {
            TextEntry te = mTextRects.get(i);
            canvas.save();
            canvas.translate(-mTmpLocation[0], -mTmpLocation[1]);
            canvas.concat(te.matrix);
            canvas.drawRect(0, 0, te.bounds.right - te.bounds.left, te.bounds.bottom - te.bounds.top,
                    mFramePaint);
            if (te.lineBaselines != null) {
                for (int j=0; j<te.lineBaselines.length; j++) {
                    canvas.drawLine(0, te.lineBaselines[j] - te.scrollY,
                            te.bounds.right - te.bounds.left, te.lineBaselines[j] - te.scrollY,
                            mFrameBaselinePaint);
                }
            }
            canvas.restore();
        }
    }
}
