/*
 * @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.FilterInputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public final class CheckedStream {
    
    private CheckedStream() {
        // utility class
    }
    
    public static OutputStream wrap(OutputStream ostream) {
        return ostream instanceof OStream ? (OStream)ostream : new OStream(ostream);
    }
    
    public static InputStream wrap(InputStream istream) {
        return istream instanceof IStream ? (IStream)istream : new IStream(istream);
    }
    
    private static final class OStream extends FilterOutputStream {
        
        private boolean closed = false;

        public OStream(OutputStream out) {
            super(out);
        }
        
        @Override
        public void write(byte[] data, int off, int len) throws IOException {
            checkstate();
            super.write(data, off, len);
        }

        @Override
        public void write(int bytedata) throws IOException {
            checkstate();
            super.write(bytedata);
        }

		@Override
		public void flush() throws IOException {
			checkstate();
			super.flush();
		}
        
        @Override
        public void close() throws IOException {
            checkstate();
            closed = true;
        }

        @Override
        public String toString() {
            return out.toString();
        }

        private void checkstate() throws IOException {
            if(closed) {
                throw new IOException("already closed");
            }
        }

    }
    
    private static final class IStream extends FilterInputStream {
        
        private boolean closed = false;

        public IStream(InputStream istream) {
            super(istream);
        }
        
        @Override
        public void reset() throws IOException {
            checkstate();
            super.reset();
        }

        @Override
        public int available() throws IOException {
            checkstate();
            return super.available();
        }

        @Override
        public long skip(long n) throws IOException {
            checkstate();
            return super.skip(n);
        }

        @Override
        public int read(byte[] target, int off, int len) throws IOException {
            checkstate();
            return super.read(target, off, len);
        }

        @Override
        public int read() throws IOException {
            checkstate();
            return super.read();
        }

        @Override
        public int read(byte[] target) throws IOException {
            checkstate();
            return super.read(target);
        }
        
        @Override
        public void close() throws IOException {
            checkstate();
            closed = true;
        }
        
        @Override
        public String toString() {
            return in.toString();
        }

        private void checkstate() throws IOException {
            if(closed) {
                throw new IOException("already closed");
            }
        }

    }
    
}
