/*
 * Copyright (C) 2020 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 android.util;

import android.annotation.NonNull;
import android.annotation.Nullable;

import java.io.PrintWriter;
import java.io.Writer;
import java.util.Arrays;

/**
 * Lightweight wrapper around {@link PrintWriter} that automatically indents
 * newlines based on internal state. It also automatically wraps long lines
 * based on given line length.
 * <p>
 * Delays writing indent until first actual write on a newline, enabling indent
 * modification after newline.
 *
 * @hide
 */
public class IndentingPrintWriter extends PrintWriter {
    private final String mSingleIndent;
    private final int mWrapLength;

    /** Mutable version of current indent */
    private StringBuilder mIndentBuilder = new StringBuilder();
    /** Cache of current {@link #mIndentBuilder} value */
    private char[] mCurrentIndent;
    /** Length of current line being built, excluding any indent */
    private int mCurrentLength;

    /**
     * Flag indicating if we're currently sitting on an empty line, and that
     * next write should be prefixed with the current indent.
     */
    private boolean mEmptyLine = true;

    private char[] mSingleChar = new char[1];

    public IndentingPrintWriter(@NonNull Writer writer) {
        this(writer, "  ", -1);
    }

    public IndentingPrintWriter(@NonNull Writer writer, @NonNull String singleIndent) {
        this(writer, singleIndent, null, -1);
    }

    public IndentingPrintWriter(@NonNull Writer writer, @NonNull String singleIndent,
            String prefix) {
        this(writer, singleIndent, prefix, -1);
    }

    public IndentingPrintWriter(@NonNull Writer writer, @NonNull String singleIndent,
            int wrapLength) {
        this(writer, singleIndent, null, wrapLength);
    }

    public IndentingPrintWriter(@NonNull Writer writer, @NonNull String singleIndent,
            @Nullable String prefix, int wrapLength) {
        super(writer);
        mSingleIndent = singleIndent;
        mWrapLength = wrapLength;
        if (prefix != null) {
            mIndentBuilder.append(prefix);
        }
    }

    /**
     * Overrides the indent set in the constructor for the next printed line.
     *
     * @deprecated Use the "prefix" constructor parameter
     * @hide
     */
    @NonNull
    @Deprecated
    public IndentingPrintWriter setIndent(@NonNull String indent) {
        mIndentBuilder.setLength(0);
        mIndentBuilder.append(indent);
        mCurrentIndent = null;
        return this;
    }

    /**
     * Overrides the indent set in the constructor with {@code singleIndent} repeated {@code indent}
     * times.
     *
     * @deprecated Use the "prefix" constructor parameter
     * @hide
     */
    @NonNull
    @Deprecated
    public IndentingPrintWriter setIndent(int indent) {
        mIndentBuilder.setLength(0);
        for (int i = 0; i < indent; i++) {
            increaseIndent();
        }
        return this;
    }

    /**
     * Increases the indent starting with the next printed line.
     */
    @NonNull
    public IndentingPrintWriter increaseIndent() {
        mIndentBuilder.append(mSingleIndent);
        mCurrentIndent = null;
        return this;
    }

    /**
     * Decreases the indent starting with the next printed line.
     */
    @NonNull
    public IndentingPrintWriter decreaseIndent() {
        mIndentBuilder.delete(0, mSingleIndent.length());
        mCurrentIndent = null;
        return this;
    }

    /**
     * Prints a key-value pair.
     */
    @NonNull
    public IndentingPrintWriter print(@NonNull String key, @Nullable Object value) {
        String string;
        if (value == null) {
            string = "null";
        } else if (value.getClass().isArray()) {
            if (value.getClass() == boolean[].class) {
                string = Arrays.toString((boolean[]) value);
            } else if (value.getClass() == byte[].class) {
                string = Arrays.toString((byte[]) value);
            } else if (value.getClass() == char[].class) {
                string = Arrays.toString((char[]) value);
            } else if (value.getClass() == double[].class) {
                string = Arrays.toString((double[]) value);
            } else if (value.getClass() == float[].class) {
                string = Arrays.toString((float[]) value);
            } else if (value.getClass() == int[].class) {
                string = Arrays.toString((int[]) value);
            } else if (value.getClass() == long[].class) {
                string = Arrays.toString((long[]) value);
            } else if (value.getClass() == short[].class) {
                string = Arrays.toString((short[]) value);
            } else {
                string = Arrays.toString((Object[]) value);
            }
        } else {
            string = String.valueOf(value);
        }
        print(key + "=" + string + " ");
        return this;
    }

    /**
     * Prints a key-value pair, using hexadecimal format for the value.
     */
    @NonNull
    public IndentingPrintWriter printHexInt(@NonNull String key, int value) {
        print(key + "=0x" + Integer.toHexString(value) + " ");
        return this;
    }

    @Override
    public void println() {
        write('\n');
    }

    @Override
    public void write(int c) {
        mSingleChar[0] = (char) c;
        write(mSingleChar, 0, 1);
    }

    @Override
    public void write(@NonNull String s, int off, int len) {
        final char[] buf = new char[len];
        s.getChars(off, len - off, buf, 0);
        write(buf, 0, len);
    }

    @Override
    public void write(@NonNull char[] buf, int offset, int count) {
        final int indentLength = mIndentBuilder.length();
        final int bufferEnd = offset + count;
        int lineStart = offset;
        int lineEnd = offset;

        // March through incoming buffer looking for newlines
        while (lineEnd < bufferEnd) {
            char ch = buf[lineEnd++];
            mCurrentLength++;
            if (ch == '\n') {
                maybeWriteIndent();
                super.write(buf, lineStart, lineEnd - lineStart);
                lineStart = lineEnd;
                mEmptyLine = true;
                mCurrentLength = 0;
            }

            // Wrap if we've pushed beyond line length
            if (mWrapLength > 0 && mCurrentLength >= mWrapLength - indentLength) {
                if (!mEmptyLine) {
                    // Give ourselves a fresh line to work with
                    super.write('\n');
                    mEmptyLine = true;
                    mCurrentLength = lineEnd - lineStart;
                } else {
                    // We need more than a dedicated line, slice it hard
                    maybeWriteIndent();
                    super.write(buf, lineStart, lineEnd - lineStart);
                    super.write('\n');
                    mEmptyLine = true;
                    lineStart = lineEnd;
                    mCurrentLength = 0;
                }
            }
        }

        if (lineStart != lineEnd) {
            maybeWriteIndent();
            super.write(buf, lineStart, lineEnd - lineStart);
        }
    }

    private void maybeWriteIndent() {
        if (mEmptyLine) {
            mEmptyLine = false;
            if (mIndentBuilder.length() != 0) {
                if (mCurrentIndent == null) {
                    mCurrentIndent = mIndentBuilder.toString().toCharArray();
                }
                super.write(mCurrentIndent, 0, mCurrentIndent.length);
            }
        }
    }
}
