package org.apache.commons.compress.compressors;

import com.one.ArchiveContainer;
import com.one.ArchiveEntry;
import com.one.FileInputStream;
import com.one.PartialInputStream;
import com.one.ProgressBar;
import com.one.RandomAccessInputStream;
import com.one.ReplaceableInputStream;
import com.one.file.Connector;
import com.one.file.FileConnection;
import com.vmx.AuxClass;
import com.vmx.Locale;
import com.vmx.ProgressCallback;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Hashtable;

public abstract class SingleFileContainer extends ArchiveContainer
{
	protected ArchiveEntry entry;

	public void readEntries() throws IOException
	{
		entries = new Hashtable();

		String name = file.getName();
		int index = name.lastIndexOf('.');

		if(index > 0 && name.lastIndexOf('.', index - 1) > 0)
		{
			name = name.substring(0, index);
		}
		else
		{
			name = "file.contents";
		}

		entry = new ArchiveEntry(name);

		entry.setCompressedSize((int)file.fileSize());
		entry.setLastModified(file.lastModified());

		entries.put(name, entry);
		addFile(name);
	}
	
	public abstract CompressorInputStream getCompressorInputStream(InputStream is) throws IOException;
	public abstract CompressorOutputStream getCompressorOutputStream(OutputStream os) throws IOException;

	public InputStream getInputStream(ArchiveEntry entry) throws IOException
	{
		checkClosed();
		return getCompressorInputStream(new PartialInputStream(rais, -1, -1));
	}

	protected ArchiveEntry createActualEntry(RandomAccessInputStream source, String name, long time, ProgressCallback callback) throws IOException
	{
		if(entries.size() > 0)
		{
			throw new CompressorException("You have to delete the existing file from the archive before adding new one.\nYou can ignore the \"error\" part of this message.");
		}

		if(rais instanceof ReplaceableInputStream)
		{
			ReplaceableInputStream ris = (ReplaceableInputStream)rais;

			RandomAccessInputStream replace = ris.getReplaceStream();

			rais = ris.getBaseStream();
			ris.close();

			if(replace instanceof FileInputStream)
			{
				FileConnection fc = ((FileInputStream)replace).getBaseConnection();

				replace.close();

				Connector.releaseTempFile(fc.getPath() + fc.getName());

				fc.delete();
				fc.close();
			}
			else
			{
				replace.close();
			}
		}

		FileConnection fc = (FileConnection)Connector.open("file:///" + Connector.createTempFile(file.getPath(), false));
		fc.create();

		OutputStream os = getCompressorOutputStream(fc.openOutputStream());

		if(source != null)
		{
			byte[] buf = new byte[AuxClass.ARCBUFSIZE];
			int len;

			if(callback != null)
			{
				while(source.available() > 0)
				{
					len = source.read(buf);
					os.write(buf, 0, len);

					callback.progress(len);
				}
			}
			else
			{
				while(source.available() > 0)
				{
					len = source.read(buf);
					os.write(buf, 0, len);
				}
			}

			source.close();
		}

		os.close();

		rais = new ReplaceableInputStream(rais);
		((ReplaceableInputStream)rais).setReplace(new FileInputStream(fc), 0, rais.getCapacity());

		if(entry != null)
		{
			entries.remove(entry.getName());
			deleteFile(entry.getName());
		}

		return entry = new ArchiveEntry(name);
	}

	protected void deleteActualEntry(ArchiveEntry entry) throws IOException
	{
	}

	protected void renameActualEntry(ArchiveEntry entry, String newName) throws IOException
	{
		throw new CompressorException("Rename the archive itself instead of renaming this *virtual* file.\nYou can ignore the \"error\" part of this message.");
	}

//	protected void renameBaseFile(String newName) throws IOException
//	{
//		String name = file.getName();
//		System.out.println("Renaming base file from " + name + " for " + newName);
//
//		if(name.equals(newName))
//		{
//			return;
//		}
//
//		int index = name.lastIndexOf('.');
//
//		if(index > 0)
//		{
//			rais.pause();
//			file.rename(newName + name.substring(index));
//			rais.resume();
//		}
//
//		String path = file.getPath();
//
//		if(path.startsWith("/"))
//		{
//			path = path.substring(1);
//		}
//
//		TransparentConnector.renameContainer(path + name, path + file.getName());
//
//		if(listener != null)
//		{
//			listener.containerStateChanged(this);
//		}
//	}

	public void finish() throws IOException
	{
		if(finished)
		{
			return;
		}

		checkReadOnly();

		ProgressCallback callback = ProgressBar.getProgressCallback();
		ProgressBar.show();

		callback.setText(Locale.getString(super.getClass().getName(), Locale.WRITING_FILE, file.getName()));

		if(rais instanceof ReplaceableInputStream)
		{
			file = AuxClass.updateFileData(file, (ReplaceableInputStream)rais, callback);
		}
		else
		{
			rais.close();
		}

		finished = true;

		rais = new FileInputStream(file);

		ProgressBar.hide();
	}
}
