package com.one;

import com.vmx.*;
import java.io.*;
import java.util.*;

public class PlainPackage extends ArchiveContainer
{
	protected void readEntries() throws IOException
	{
		entries = new Hashtable();

		BufDataInputStream dis = new BufDataInputStream(rais);
		ArchiveEntry entry;

		try
		{
			while(true)
			{
				entry = new ArchiveEntry();
				entry.name = dis.readUTF();
				entry.size = dis.readInt();
				entry.offset = dis.getPosition();

				if(entry.name.length() > 0 && entry.size >= 0)
				{
					entries.put(entry.name, entry);
					dis.skip(entry.size);
				}
				else
				{
					break;
				}

				addFile(entry.name);
			}
		}
		catch(EOFException eofe)
		{
			finished = false;
		}
	}

	public InputStream getInputStream(ArchiveEntry entry) throws IOException
	{
		if(entry == null)
		{
			return null;
		}

		checkClosed();

		return new PartialInputStream(rais, entry.offset, entry.size);
	}

	protected ArchiveEntry createActualEntry(RandomAccessInputStream source, String name, long time, ProgressCallback callback) throws IOException
	{
		ArchiveEntry entry = new ArchiveEntry();
		entry.name = name;
		entry.size = source != null ? source.getCapacity() : 0;
		entry.offset = finished ? (int)file.fileSize() - 6 : (int)file.fileSize();

		DataOutputStream os = new DataOutputStream(file.openOutputStream(entry.offset));

		os.writeUTF(entry.name);
		os.writeInt(entry.size);

		if(source != null)
		{
			byte[] buf = new byte[AuxClass.COPYBUFSIZE];
			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.update();

		return entry;
	}

	protected void deleteActualEntry(ArchiveEntry entry) throws IOException
	{
		if(finished)
		{
			rais.pause();
			file.truncate(file.fileSize() - 6);
			rais.resume();
		}

		rais = new ReplaceableInputStream(rais);

		int hdrsize = 2 + StringEncoder.getEncodedLength(entry.getName(), StringEncoder.ENC_UTF8) + 4;
		int delta = ((ReplaceableInputStream)rais).setReplace(new byte[0], entry.offset - hdrsize, entry.offset + entry.size);

		updateOffset(entry.offset, delta);
	}

	protected void renameActualEntry(ArchiveEntry entry, String newName) throws IOException
	{
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(baos);

		dos.writeUTF(entry.name);
		int namelen = baos.size();

		entry.setName(newName);

		baos.reset();
		dos.writeUTF(newName);
		byte[] b = baos.toByteArray();

		dos.close();

		if(finished)
		{
			rais.pause();
			file.truncate(file.fileSize() - 6);
			rais.resume();
		}

		rais = new ReplaceableInputStream(rais);

		int delta = ((ReplaceableInputStream)rais).setReplace(b, entry.offset, entry.offset + namelen);

		updateOffset(entry.offset, delta);
	}

	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();
		}

		DataOutputStream dos = new DataOutputStream(file.openOutputStream(file.fileSize()));

		dos.writeUTF("");
		dos.writeInt(-1);

		dos.close();

		finished = true;

		rais = new FileInputStream(file);

		ProgressBar.hide();
	}
}
