/*
 * Copyright 2013 Yuichiro Moriguchi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.morilib.nina.translate.sh;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import net.morilib.sh.ShFile;
import net.morilib.sh.ShFileSystem;
import net.morilib.sh.ShProcess;
import net.morilib.sh.ShStat;
import net.morilib.sh.misc.FileTypeUtils;

public class ShNinaRealFile implements ShFile {

	/**
	 * 
	 */
	protected ShFileSystem filesystem;

	/**
	 * 
	 */
	protected String virtualpath;

	/**
	 * 
	 */
	protected File file;

	/**
	 * 
	 * @param fs
	 * @param virtualpath
	 * @param file
	 */
	public ShNinaRealFile(ShFileSystem fs, String virtualpath,
			File file) {
		this.filesystem  = fs;
		this.virtualpath = virtualpath;
		this.file = file;
	}

	public Collection<ShFile> getFiles() {
		SortedSet<String> z;
		List<ShFile> l;
		String[] a;
		ShFile f;

		if((a = file.list()) == null) {
			return Collections.emptyList();
		} else {
			l = new ArrayList<ShFile>();
			z = new TreeSet<String>(Arrays.asList(a));
			for(String s : z) {
				f = filesystem.getFile(virtualpath, s);
				l.add(f);
			}
			return l;
		}
	}

	public InputStream getInputStream() throws IOException {
		return new FileInputStream(file);
	}

	public String getName() {
		return file.getName();
	}

	public PrintStream getPrintStream(
			boolean append) throws IOException {
		return new PrintStream(new FileOutputStream(file, append));
	}

	public boolean isDirectory() {
		return file.isDirectory();
	}

	public boolean isExecutable() {
		if(file.isDirectory()) {
			return true;
		} else if(file.isFile()) {
			return FileTypeUtils.parseShebang(this) != null;
		} else {
			return false;
		}
	}

	public boolean isExist() {
		return file.exists();
	}

	public boolean isFile() {
		return file.isFile();
	}

	public long getLastModified() {
		return file.lastModified();
	}

	public boolean isReadable() {
		return file.canRead();
	}

	public boolean isWritable() {
		return file.canWrite();
	}

	/* (non-Javadoc)
	 * @see net.morilib.sh.ShFile#isHidden()
	 */
	public boolean isHidden() {
		return file.isHidden();
	}

	public boolean isZeroFile() {
		return file.length() == 0;
	}

	public ShFile toAbsolute() {
		if(virtualpath.length() > 0 && virtualpath.charAt(0) == '/') {
			return filesystem.getFile(virtualpath);
		} else {
			return filesystem.getFile(
					filesystem.getCurrentDirectory().toString(),
					virtualpath);
		}
	}

	public ShFile toCanonical() {
		List<String> l = new ArrayList<String>();
		StringBuffer b = new StringBuffer("");
		String[] a;

		a = toAbsolute().toString().replaceFirst("/+", "").split("/");
		for(String t : a) {
			if(t.equals(".")) {
				// do nothing
			} else if(!t.equals("..")) {
				l.add(t);
			} else if(l.size() > 0) {
				l.remove(l.size() - 1);
			}
		}
		for(String t : l)  b.append("/").append(t);
		return filesystem.getFile(b.toString());
	}

	public boolean mkdir() {
		return file.mkdir();
	}

	public boolean renameTo(ShFile f) {
		return false;
	}

	public void setLastModified(long time) {
		file.setLastModified(time);
	}

	public boolean rmdir() {
		return file.isDirectory() && file.delete();
	}

	public boolean deleteFile() {
		return file.isFile() && file.delete();
	}

	public ShStat getStat() {
		ShStat r = new ShStat();
		int f = 0;

		r.setFilename(virtualpath);
		r.setMtime(file.lastModified());
		r.setSize(file.length());
		f |= isDirectory()  ? ShStat.DIRECTORY : 0;
		f |= isExecutable() ? ShStat.EXECUTABLE : 0;
		f |= isWritable()   ? ShStat.WRITABLE : 0;
		f |= isReadable()   ? ShStat.READABLE : 0;
		r.setFlags(f);
		return r;
	}

	public ShProcess getProcess() {
		return null;
	}

	public String toString() {
		return virtualpath;
	}

}
