/*
 * Copyright (C) 2006 Mikhail A. Kryshen
 *
 * $Id: ReplaceWriter.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $
 */

package kryshen.tema;

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

import java.util.LinkedList;
import java.util.Iterator;

/**
 * FilterWriter which replaces characters with escape strings.
 *
 * @author Mikhail A. Kryshen
 */
class ReplaceWriter extends FilterWriter {
    private String[] patterns;
    private String[] replaces;

    private String prefix;
    private String postfix;

    private int maxPatternLength = 0;

    /** Had this Writer processed any data? */
    private boolean processedData = false;

    private StringBuffer buffer = new StringBuffer();

    public ReplaceWriter(Writer w, String pattern, String replace) {
        this(w, new String[]{pattern}, new String[]{replace});
    }

    public ReplaceWriter(Writer w, String pattern, String replace,
                         String prefix, String postfix) {

        this(w, new String[]{pattern}, new String[]{replace}, 
             prefix, postfix);
    }

    public ReplaceWriter(Writer w, String[] patterns, String[] replaces) {
        this(w, patterns, replaces, null, null);
    }

    public ReplaceWriter(Writer w, String[] patterns, String[] replaces, 
                         String prefix, String postfix) {
	super(w);
        
	this.patterns = patterns;
	this.replaces = replaces;
        
        this.prefix = prefix;
        this.postfix = postfix;
        
	for (int i = 0; i < patterns.length; i++) {
	    int length = patterns[i].length();
	    if (length > maxPatternLength)
		maxPatternLength = length;
	}
    }

    private boolean processBuffer(int minLength) throws IOException {
        if (buffer.length() == 0) return false;

        if (!processedData) {
            if (prefix != null)
                super.write(prefix, 0, prefix.length());
            processedData = true;
        }

        int k;
	for (k = 0; minLength + k < buffer.length(); k++) {
	    for (int i = 0; i < patterns.length; i++) {
		String pattern = patterns[i];
		int length = pattern.length();

                if (length + k > buffer.length())
                    continue;

		boolean match = true;

		for (int j = 0; j < length; j++) {
		    if (pattern.charAt(j) != buffer.charAt(j + k)) {
			match = false;
                        break;
		    }
		}

		if (match) {
                    super.write(buffer.substring(0, k), 0, k);
                    buffer.delete(0, k + length);
                    super.write(replaces[i], 0, replaces[i].length());
		    return true;
		}
	    }
	}

        super.write(buffer.substring(0, k), 0, k);
        buffer.delete(0, k);

        return false;
    }

    public void write(int c) throws IOException {
	buffer.append((char)c);
	processBuffer(maxPatternLength);
    }

    public void write(char[] cbuf, int off, int len) throws IOException {
	for (int i = off; i < off + len; i++) {
	    buffer.append(cbuf[i]);
	}
	processBuffer(maxPatternLength);
    }

    public void write(String str, int off, int len) throws IOException {
        buffer.append(str.substring(off, off + len));
	processBuffer(maxPatternLength);
    }

    public void finish() throws IOException {
        while (processBuffer(0));

//         super.write(buffer.toString(), 0, buffer.length());
//         buffer.delete(0, buffer.length());

        if (processedData && postfix != null)
            super.write(postfix, 0, postfix.length());
    }

    public void close() throws IOException {
        finish();
        super.close();
    }
}