/*
 * 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.dx.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;
    }
}
