package net.sourceforge.rtf.document;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

/**
 * This class contains all RTF Element of one RTF document.
 *  
 * @version 1.0.0
 * @author <a href="mailto:angelo.zerr@gmail.com">Angelo ZERR</a>
 *
 */
public class RTFDocument extends RTFElement {

	private List stringBufferList = null;
	public RTFDocument() {
	}
	
	public RTFDocument(RTFDocument document) {
		super(document);
	}
	
	public void save(String fileName) throws IOException {
		File file = new File(fileName);
		save (file);
	}
	
	public void save(File file) throws IOException {
		FileWriter writer = new FileWriter(file);
		save (writer);
	}
	
	public void save(Writer writer) throws IOException {
		// loop for RTFElement of RTFDocument
		List rtfStringList = getAllRTFStringList();
		for (Iterator iter = rtfStringList.iterator(); iter.hasNext();) {
			String stringElement = (String) iter.next();
			writer.write(stringElement);
		}
		writer.close();
	}
	
	public Reader getReader() throws IOException  {
		return new RTFDocumentReader(this);
	}
	
	private List getAllRTFStringList() throws IOException {
		if (stringBufferList == null) {
			stringBufferList = new ArrayList();
			Vector elementList = getElementList();
			setAllRTFStringList(elementList);
		}
		return stringBufferList;
	}
	
	private void setAllRTFStringList(Vector elementList) throws IOException {
		for (Iterator iter = elementList.iterator(); iter.hasNext();) {
			Object element = (Object) iter.next();
			if (element instanceof StringBuffer) {
				// Current element is RTF code
				StringBuffer stringElement = (StringBuffer)element;
                if (stringElement != null && stringElement.length() > 0)
                    stringBufferList.add(stringElement.toString());
			}
			else {
				if (element instanceof RTFElement) {
					RTFElement rtfElement = (RTFElement)element; 
					// Current Element is RTFElement
					setAllRTFStringList(rtfElement.getElementList());
				}
				else {
					// Error
					throw new IOException("Error while save RTFDocument. RTFDocument must contain RTFElement or StringBuffer.");
				}
			}
		}
	}

	public class RTFDocumentReader extends Reader {


		private Reader reader ; // current Reader
		private int index;
		private int size;
		private List rtfStringList = null;

		
		public RTFDocumentReader(RTFDocument document) throws IOException {
			this.rtfStringList = document.getAllRTFStringList();
			this.size = rtfStringList.size();
			index = 0;
			createReader(index++ );
		}
		
		
		public int read() throws IOException {
		   int ch = reader.read();
		   if( ch == -1 ){
		     if( nextReader() ){
		       ch = reader.read();
		     } // if no next reader return -1
		   }
		   return ch ;
		}
		
		public int read(char[] cbuf) throws IOException {
			return read( cbuf, 0, cbuf.length ) ;
		}

			 public int read(char[] cbuf, int off, int len)
			      throws IOException {
			   int ct = reader.read( cbuf, off, len );
			   if( ct == -1 ){
			     if( nextReader() ){
			       ct = reader.read( cbuf, off, len );
			     } // if no next reader return -1
			   }

			   return ct ;
			 }
		
		public void close() throws IOException {

		}
		
//		 return true if next reader created ok
		 private boolean nextReader() throws IOException {
			 if (size > index ) {
				 createReader(index++);
				 return true;
			 }
			 return false;
		 }
		
		private void createReader( int index) throws IOException { 
			String rtfString = (String)rtfStringList.get(index);
            reader = new StringReader(rtfString);
		}
		
		public Reader getCurrentReader() {
			return reader;
		}

	}
	
	

}
