/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.io;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import net.ranides.assira.text.TextEncoding;

/**
 *
 * @author ranides
 */
public class LocalOutputStream extends OutputStream {
    
    public static final LocalOutputStream NULL_STREAM = toStream(NullOutputStream.INSTANCE);
    
    private final File file;
    private final OutputStream delegate;
    
    /**
     * Tworzy nowy obiekt powiązany z podaną nazwą pliku oraz strumieniem.
     * @param file
     * @param delegate
     */
    protected LocalOutputStream(File file, OutputStream delegate) {
        this.file = file;
        this.delegate = delegate;
    }
    
    public static LocalOutputStream toFile(File file) throws FileNotFoundException {
        return new LocalOutputStream(file, new FileOutputStream(file));
    }
    
    public static LocalOutputStream toText() {
        return toText(new File("anonymous"));
    }
    
    public static LocalOutputStream toText(Charset charset) {
        return toText(new File("anonymous"), charset);
    }
    
    public static LocalOutputStream toText(File path) {
        return new LocalOutputStream(path, new StrStream(TextEncoding.NIO_UTF8));
    }
    
    public static LocalOutputStream toText(File path, Charset charset) {
        return new LocalOutputStream(path, new StrStream(charset));
    }
    
    public static LocalOutputStream toStream(OutputStream ostream) {
        return toStream(new File("anonymous"), ostream);
    }
    
    public static LocalOutputStream toStream(File path, OutputStream ostream) {
        return new LocalOutputStream(path, ostream);
    }
    
    public static LocalOutputStream toNull() {
        return NULL_STREAM;
    }
    
    /**
     * Zwraca nazwę pliku skojarzonego ze strumieniem. Nie musi być to ścieżka 
     * reprezentująca fizyczny plik, do którego zapisywana jest treść.
     * @return
     */
    public File file() {
        return file;
    }

    @Override
    public void write(int ibyte) throws IOException {
        delegate.write(ibyte);
    }

    @Override
    public void write(byte[] bytes) throws IOException {
        delegate.write(bytes);
    }

    @Override
    public void write(byte[] bytes, int offset, int length) throws IOException {
        delegate.write(bytes, offset, length);
    }

    @Override
    public void flush() throws IOException {
        delegate.flush();
    }

    @Override
    public void close() throws IOException {
        delegate.close();
    }

    @Override
    public String toString() {
        return delegate.toString();
    }
    
    private static final class StrStream extends ByteArrayOutputStream {
        private final Charset charset;

        public StrStream(Charset charset) {
            this.charset = charset;
        }

        @Override
        public String toString() {
            try {
                return this.toString(charset.name());
            } catch(UnsupportedEncodingException cause) {
                throw new RIOException(cause);
            }
        }
        
    }
    
}
