/*
 * Copyright (c) 2004-2017, by Alex Leigh.
 * All rights reserved.
 *
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE
 * The copyright notice above does not evidence any
 * actual or intended publication of such source code.
 */

package lc.mecha.util;

import java.util.Collection;

/**
 * This class provides an easy mechanism for creating strings out of delimited
 * tokens.
 */

public final class StringAccumulator implements Cloneable {
    private final String token;
    private String quote;
    private final StringBuilder sb = new StringBuilder();
    private boolean shouldDelim = false;

    public StringAccumulator(final String token) {
        this(token, false);
    }

    public StringAccumulator(final String token, final boolean leading) {
        this.token = token;
        if (leading) {
            sb.append(token);
        }
    }

    public String getQuote() {
        return quote;
    }

    public void setQuote(String quote) {
        this.quote = quote;
    }

    public static String concatArray(final String[] array, final int length, final String delim, final boolean leading) {
        final StringAccumulator sa = new StringAccumulator(delim, leading);
        for (int i = 0; i < length; i++) {
            sa.append(array[i]);
        }
        return sa.asString();
    }

    public int length() {
        return asString().length();
    }

    public void appendAll(final Collection<String> col) {
        for (final String s : col) append(s);
    }

    public void appendAll(final String... value) {
        for (final String s : value) {
            append(s);
        }
    }

    /**
     * Append the given string the given number of times.
     *
     * @param value The string to add.
     * @param cnt   The number of copies to add.
     */
    public void appendRepeat(final String value, int cnt) {
        for (int i = 0; i < cnt; i++)
            append(value);
    }

    /**
     * Append the provided token to the accumulated string. If a token has
     * already been added to the accumulator, the delimiter will be used to
     * separate the tokens.
     *
     * @param s The string to add.
     * @return StringAccumulator this.
     */
    public StringAccumulator append(final String s) {
        // We use the boolean flag for performance rather than length()
        if (shouldDelim) {
            sb.append(token);
            if (quote != null) sb.append(quote);
            sb.append(s);
            if (quote != null) sb.append(quote);
        } else {
            if (quote != null) sb.append(quote);
            sb.append(s);
            if (quote != null) sb.append(quote);
            shouldDelim = true;
        }
        return this;
    }

    /**
     * Return a clone of this object.
     *
     * @return A cline.
     */
    public Object clone() {
        final StringAccumulator n = new StringAccumulator(token, false);
        n.append(asString());
        return n;
    }

    public String asString() {
        return sb.toString();
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        final StringAccumulator that = (StringAccumulator) o;

        return !(!sb.equals(that.sb));
    }

    @Override
    public int hashCode() {
        return sb.hashCode();
    }

    @Override
    public String toString() {
        return asString();
    }
}
