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

import java.io.FilterWriter;
import java.io.IOException;
import java.io.Writer;

/**
 * Writer that wraps another writer and passes width-limited and
 * optionally-prefixed output to its subordinate. When lines are
 * wrapped they are automatically indented based on the start of the
 * line.
 */
public final class IndentingWriter extends FilterWriter {
    /** {@code null-ok;} optional prefix for every line */
    private final String prefix;

    /** {@code > 0;} the maximum output width */
    private final int width;

    /** {@code > 0;} the maximum indent */
    private final int maxIndent;

    /** {@code >= 0;} current output column (zero-based) */
    private int column;

    /** whether indent spaces are currently being collected */
    private boolean collectingIndent;

    /** {@code >= 0;} current indent amount */
    private int indent;

    /**
     * Constructs an instance.
     *
     * @param out {@code non-null;} writer to send final output to
     * @param width {@code >= 0;} the maximum output width (not including
     * {@code prefix}), or {@code 0} for no maximum
     * @param prefix {@code non-null;} the prefix for each line
     */
    public IndentingWriter(Writer out, int width, String prefix) {
        super(out);

        if (out == null) {
            throw new NullPointerException("out == null");
        }

        if (width < 0) {
            throw new IllegalArgumentException("width < 0");
        }

        if (prefix == null) {
            throw new NullPointerException("prefix == null");
        }

        this.width = (width != 0) ? width : Integer.MAX_VALUE;
        this.maxIndent = width >> 1;
        this.prefix = (prefix.length() == 0) ? null : prefix;

        bol();
    }

    /**
     * Constructs a no-prefix instance.
     *
     * @param out {@code non-null;} writer to send final output to
     * @param width {@code >= 0;} the maximum output width (not including
     * {@code prefix}), or {@code 0} for no maximum
     */
    public IndentingWriter(Writer out, int width) {
        this(out, width, "");
    }

    /** {@inheritDoc} */
    @Override
    public void write(int c) throws IOException {
        synchronized (lock) {
            if (collectingIndent) {
                if (c == ' ') {
                    indent++;
                    if (indent >= maxIndent) {
                        indent = maxIndent;
                        collectingIndent = false;
                    }
                } else {
                    collectingIndent = false;
                }
            }

            if ((column == width) && (c != '\n')) {
                out.write('\n');
                column = 0;
                /*
                 * Note: No else, so this should fall through to the next
                 * if statement.
                 */
            }

            if (column == 0) {
                if (prefix != null) {
                    out.write(prefix);
                }

                if (!collectingIndent) {
                    for (int i = 0; i < indent; i++) {
                        out.write(' ');
                    }
                    column = indent;
                }
            }

            out.write(c);

            if (c == '\n') {
                bol();
            } else {
                column++;
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public void write(char[] cbuf, int off, int len) throws IOException {
        synchronized (lock) {
            while (len > 0) {
                write(cbuf[off]);
                off++;
                len--;
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public void write(String str, int off, int len) throws IOException {
        synchronized (lock) {
            while (len > 0) {
                write(str.charAt(off));
                off++;
                len--;
            }
        }
    }

    /**
     * Indicates that output is at the beginning of a line.
     */
    private void bol() {
        column = 0;
        collectingIndent = (maxIndent != 0);
        indent = 0;
    }
}
