package org.jivesoftware.smack.util;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

public class ObservableWriter extends Writer {
   Writer wrappedWriter = null;
   List<WriterListener> listeners = new ArrayList();

   public ObservableWriter(Writer wrappedWriter) {
      this.wrappedWriter = wrappedWriter;
   }

   public void write(char[] cbuf, int off, int len) throws IOException {
      this.wrappedWriter.write(cbuf, off, len);
      String str = new String(cbuf, off, len);
      this.notifyListeners(str);
   }

   public void flush() throws IOException {
      this.wrappedWriter.flush();
   }

   public void close() throws IOException {
      this.wrappedWriter.close();
   }

   public void write(int c) throws IOException {
      this.wrappedWriter.write(c);
   }

   public void write(char[] cbuf) throws IOException {
      this.wrappedWriter.write(cbuf);
      String str = new String(cbuf);
      this.notifyListeners(str);
   }

   public void write(String str) throws IOException {
      this.wrappedWriter.write(str);
      this.notifyListeners(str);
   }

   public void write(String str, int off, int len) throws IOException {
      this.wrappedWriter.write(str, off, len);
      str = str.substring(off, off + len);
      this.notifyListeners(str);
   }

   private void notifyListeners(String str) {
      WriterListener[] writerListeners = null;
      synchronized(this.listeners) {
         writerListeners = new WriterListener[this.listeners.size()];
         this.listeners.toArray(writerListeners);
      }

      for(int i = 0; i < writerListeners.length; ++i) {
         writerListeners[i].write(str);
      }

   }

   public void addWriterListener(WriterListener writerListener) {
      if (writerListener != null) {
         synchronized(this.listeners) {
            if (!this.listeners.contains(writerListener)) {
               this.listeners.add(writerListener);
            }

         }
      }
   }

   public void removeWriterListener(WriterListener writerListener) {
      synchronized(this.listeners) {
         this.listeners.remove(writerListener);
      }
   }
}
