package net.morilib.sh;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Collection;

public class ShFileSystemStub implements ShFileSystem {

	static PipedInputStream in = new PipedInputStream();
	static PipedOutputStream out1 = new PipedOutputStream();
	static PipedOutputStream out2 = new PipedOutputStream();
	static PrintStream pout1 = new PrintStream(out1);
	static PrintStream pout2 = new PrintStream(out2);
	public static long lastModified;

	static class Fl1 implements ShFile {

		ShFile root;
		String name;

		Fl1(ShFile r, String s) {
			root = r;
			name = s;
		}

		public Collection<ShFile> getFiles() {
			return Arrays.asList(new ShFile[] {
					new Fl1(this, "haruka"),
					new Fl1(this, "chihaya"),
					new Fl1(this, "yukiho"),
					new Fl1(this, "azusa"),
					new Fl1(this, "ritsuko")
			});
		}

		public String getName() {
			return name;
		}

		public boolean isDirectory() {
			return !name.equals("notdirectory");
		}

		public boolean isExecutable() {
			return name.equals("ritsuko");
		}

		public String toRealPath() {
			return toString();
		}

		public String toString() {
			if(root == null) {
				return "";
			} else {
				return root.toString() + "/" + name;
			}
		}

		public boolean isExist() {
			return !name.equals("notexist");
		}

		public boolean isFile() {
			return !name.equals("notfile");
		}

		public boolean isReadable() {
			return !name.equals("notreadable");
		}

		public boolean isWritable() {
			return !name.equals("notwritable");
		}

		public boolean isHidden() {
			return name.length() > 0 && name.startsWith(".");
		}

		public long getLastModified() {
			if(name.equals("reference")) {
				return 1357138800000l;
			}
			return name.length() > 0 ? name.charAt(0) : -1;
		}

		public boolean isZeroFile() {
			return name.equals("zero");
		}

		public InputStream getInputStream() {
			if(name.equals("test.sh")) {
				return new ByteArrayInputStream(
						("if true;  then echo aaa; fi\n" +
						"if false; then echo bbb; fi\n" +
						"aaa=1").getBytes());
			} else if(name.equals("cut.txt")) {
				return new ByteArrayInputStream(
						"1234567890".getBytes());
			} else if(name.equals("cut2.txt")) {
				return new ByteArrayInputStream(
						"1234567890".getBytes());
			} else if(name.equals("grep1.txt")) {
				return new ByteArrayInputStream(
						"aaa\nbbb\nccc\n".getBytes());
			} else if(name.equals("grep2.txt")) {
				return new ByteArrayInputStream(
						"bbb\nccc\nddd\n".getBytes());
			} else if(name.equals("uniq1.txt")) {
				return new ByteArrayInputStream(
						"aaa\naaa\nccc\n".getBytes());
			} else if(name.equals("sort1.txt")) {
				return new ByteArrayInputStream(
						"bbb\neee\naaa\n".getBytes());
			} else if(name.equals("sort2.txt")) {
				return new ByteArrayInputStream(
						"bbb\nddd\nccc\n".getBytes());
			} else if(name.equals("sortm1.txt")) {
				return new ByteArrayInputStream(
						"aaa\nbbb\neee\n".getBytes());
			} else if(name.equals("sortm2.txt")) {
				return new ByteArrayInputStream(
						"bbb\nccc\nddd\n".getBytes());
			} else if(name.equals("sh1.sh")) {
				return new ByteArrayInputStream(
						"echo $1 $2\n".getBytes());
			} else if(name.equals("sed1.sed")) {
				return new ByteArrayInputStream(
						"s/a/b/g\n".getBytes());
			} else if(name.equals("sed1.txt")) {
				return new ByteArrayInputStream(
						"abcd\nbcde".getBytes());
			} else {
				return in;
			}
		}

		public PrintStream getPrintStream(boolean append) {
			PrintStream p = append ? pout2 : pout1;

			p.println(name);
			return p;
		}

		public ShProcess getProcess(String... args) {
			// TODO Auto-generated method stub
			return null;
		}

		public ShFile toAbsolute() {
			return new Fl1(new Fl1(null, name), name);
		}

		public boolean mkdir() {
			return true;
		}

		public boolean renameTo(ShFile f) {
			if(f instanceof Fl1) {
				root = ((Fl1)f).root;
				name = ((Fl1)f).name;
				return true;
			} else {
				return false;
			}
		}

		public void setLastModified(long time) {
			lastModified = time;
		}

		public boolean rmdir() {
			return false;
		}

		public boolean deleteFile() {
			return false;
		}

		public ShStat getStat() {
			return new ShStat();
		}

	}

	static class Fl2 implements ShFile {

		ShFile root;
		String name;

		Fl2(ShFile r, String s) {
			root = r;
			name = s;
		}

		public Collection<ShFile> getFiles() {
			return Arrays.asList(new ShFile[] {
					new Fl2(this, "takane"),
					new Fl2(this, "hibiki"),
					new Fl2(this, "miki"),
					new Fl2(this, "yayoi"),
			});
		}

		public String getName() {
			return name;
		}

		public boolean isDirectory() {
			return true;
		}

		public boolean isExecutable() {
			return false;
		}

		public String toRealPath() {
			return toString();
		}

		public String toString() {
			if(root == null) {
				return "";
			} else {
				return root.toString() + "/" + name;
			}
		}

		public boolean isExist() {
			// TODO Auto-generated method stub
			return false;
		}

		public boolean isFile() {
			// TODO Auto-generated method stub
			return false;
		}

		public boolean isReadable() {
			// TODO Auto-generated method stub
			return false;
		}

		public boolean isWritable() {
			// TODO Auto-generated method stub
			return false;
		}

		public boolean isHidden() {
			return name.length() > 0 && name.startsWith(".");
		}

		public boolean isZeroFile() {
			// TODO Auto-generated method stub
			return false;
		}

		public InputStream getInputStream() {
			// TODO Auto-generated method stub
			return null;
		}

		public PrintStream getPrintStream(boolean append) {
			// TODO Auto-generated method stub
			return null;
		}

		public ShProcess getProcess(String... args) {
			// TODO Auto-generated method stub
			return null;
		}

		public long getLastModified() {
			// TODO Auto-generated method stub
			return 0;
		}

		public ShFile toAbsolute() {
			// TODO Auto-generated method stub
			return null;
		}

		public boolean mkdir() {
			return true;
		}

		public boolean renameTo(ShFile f) {
			if(f instanceof Fl2) {
				root = ((Fl2)f).root;
				name = ((Fl2)f).name;
				return true;
			} else {
				return false;
			}
		}

		public void setLastModified(long time) {
			lastModified = time;
		}

		public boolean rmdir() {
			return false;
		}

		public boolean deleteFile() {
			return false;
		}

		public ShStat getStat() {
			return new ShStat();
		}

	}

	private ShFile realcur = new Fl1(null, "");

	public ShFile getCurrentDirectory() {
		return realcur;
	}

	public void setCurrentDirectory(ShFile s) {
		realcur = s;
	}

	public ShFile getRoot() {
		return new Fl1(null, "");
	}

	public ShFile getFile(String s) {
		return new Fl1(null, s);
	}

	public ShFile getFile(String dir, String name) {
		return new Fl1(new Fl1(new Fl1(null, ""), dir), name);
	}

	public ShFile getFile(ShFile dir, String name) {
		return new Fl1(new Fl1(new Fl1(null, ""), dir.toString()),
				name);
	}

	public ShSecurityPolicy getSecurityPolicy() {
		return ShSecurityPolicy.ALL_PERMITTED;
	}

	public ShFile getHome() {
		return getFile("/");
	}

	public InputStream getProfile() {
		return null;
	}

	public InputStream getRc() {
		return null;
	}

}
