package aQute.lib.index;

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.channels.FileChannel.MapMode;
import java.util.*;

/**
 * <pre>
 *   0   ->   0, 122   -> 1
 *   123 -> 123, 244   -> 2
 *   245 -> 245, ...
 * </pre>
 * 
 * 
 */
public class Index implements Iterable<byte[]> {
	final static int					LEAF		= 0;
	final static int					INDEX		= 1;

	final static int					SIGNATURE	= 0;
	final static int					MAGIC		= 0x494C4458;
	final static int					KEYSIZE		= 4;

	private FileChannel					file;
	final int							pageSize	= 4096;
	final int							keySize;
	final int							valueSize	= 8;
	final int							capacity;
	public Page							root;
	final LinkedHashMap<Integer, Page>	cache		= new LinkedHashMap<Integer, Index.Page>();
	final MappedByteBuffer				settings;

	private int							nextPage;

	class Page {
		final int				TYPE_OFFSET		= 0;
		final int				COUNT_OFFSET	= 2;
		final static int		START_OFFSET	= 4;
		final int				number;
		boolean					leaf;
		final MappedByteBuffer	buffer;
		int						n				= 0;
		boolean					dirty;

		Page(int number) throws IOException {
			this.number = number;
			buffer = file.map(MapMode.READ_WRITE, number * pageSize, pageSize);
			n = buffer.getShort(COUNT_OFFSET);
			int type = buffer.getShort(TYPE_OFFSET);
			leaf = type != 0;
		}

		Page(int number, boolean leaf) throws IOException {
			this.number = number;
			this.leaf = leaf;
			this.n = 0;
			buffer = file.map(MapMode.READ_WRITE, number * pageSize, pageSize);
		}

		Iterator<byte[]> iterator() {
			return new Iterator<byte[]>() {
				Iterator<byte[]>	i;
				int					rover	= 0;

				public byte[] next() {
					if (leaf) {
						return k(rover++);
					}

					return i.next();
				}

				public boolean hasNext() {
					try {
						if (leaf)
							return rover < n;
						else {
							while (i == null || i.hasNext() == false) {
								int c = (int) c(rover++);
								i = getPage(c).iterator();
							}
							return i.hasNext();
						}
					} catch (IOException e) {
						throw new RuntimeException(e);
					}

				}

				public void remove() {
					throw new UnsupportedOperationException();
				}

			};
		}

		void write() throws IOException {
			buffer.putShort(COUNT_OFFSET, (short) n);
			buffer.put(TYPE_OFFSET, (byte) (leaf ? 1 : 0));
			buffer.force();
		}

		int compare(byte[] key, int i) {
			int index = pos(i);
			for (int j = 0; j < keySize; j++, index++) {
				int a = 0;
				if (j < key.length)
					a = key[j] & 0xFF;

				int b = buffer.get(index) & 0xFF;
				if (a == b)
					continue;

				return a > b ? 1 : -1;
			}
			return 0;
		}

		int pos(int i) {
			return START_OFFSET + size(i);
		}

		int size(int n) {
			return n * (keySize + valueSize);
		}

		void copyFrom(Page page, int start, int length) {
			copy(page.buffer, pos(start), buffer, pos(0), size(length));
		}

		void copy(ByteBuffer src, int srcPos, ByteBuffer dst, int dstPos, int length) {
			if (srcPos < dstPos) {
				while (length-- > 0)
					dst.put(dstPos + length, src.get(srcPos + length));

			} else {
				while (length-- > 0)
					dst.put(dstPos++, src.get(srcPos++));
			}
		}

		long search(byte[] k) throws Exception {
			int cmp = 0;
			int i = n - 1;
			while (i >= 0 && (cmp = compare(k, i)) < 0)
				i--;

			if (leaf) {
				if (cmp != 0)
					return -1;
				else
					return c(i);
			} else {
				long value = c(i);
				Page child = getPage((int) value);
				return child.search(k);
			}
		}

		void insert(byte[] k, long v) throws IOException {
			if (n == capacity) {
				int t = capacity / 2;
				Page left = allocate(leaf);
				Page right = allocate(leaf);
				left.copyFrom(this, 0, t);
				left.n = t;
				right.copyFrom(this, t, capacity - t);
				right.n = capacity - t;
				leaf = false;
				set(0, left.k(0), left.number);
				set(1, right.k(0), right.number);
				n = 2;
				left.write();
				right.write();
			}
			insertNonFull(k, v);
		}

		byte[] k(int i) {
			buffer.position(pos(i));
			byte[] key = new byte[keySize];
			buffer.get(key);
			return key;
		}

		long c(int i) {
			if (i < 0) {
				System.out.println("Arghhh");
			}
			int index = pos(i) + keySize;
			return buffer.getLong(index);
		}

		void set(int i, byte[] k, long v) {
			int index = pos(i);
			for (int j = 0; j < keySize; j++) {
				byte a = 0;
				if (j < k.length)
					a = k[j];
				buffer.put(index + j, a);
			}
			buffer.putLong(index + keySize, v);
		}

		void insertNonFull(byte[] k, long v) throws IOException {
			int cmp = 0;
			int i = n - 1;
			while (i >= 0 && (cmp = compare(k, i)) < 0)
				i--;

			if (leaf) {
				if (cmp != 0) {
					i++;
					if (i != n)
						copy(buffer, pos(i), buffer, pos(i + 1), size(n - i));
				}
				set(i, k, v);
				n++;
				dirty = true;
			} else {
				long value = c(i);
				Page child = getPage((int) value);

				if (child.n == capacity) {
					Page left = child;
					int t = capacity / 2;
					Page right = allocate(child.leaf);
					right.copyFrom(left, t, capacity - t);
					right.n = capacity - t;
					left.n = t;
					i++; // place to insert
					if (i < n) // ok if at end
						copy(buffer, pos(i), buffer, pos(i + 1), size(n - i));
					set(i, right.k(0), right.number);
					n++;
					assert i < n;
					child = right.compare(k, 0) >= 0 ? right : left;
					left.dirty = true;
					right.dirty = true;
					this.dirty = true;
				}
				child.insertNonFull(k, v);
			}
			write();
		}

		public String toString() {
			StringBuilder sb = new StringBuilder();
			try {
				toString( sb, "");
			} catch (IOException e) {
				e.printStackTrace();
			}
			return sb.toString();
		}
		
		public void toString( StringBuilder sb, String indent ) throws IOException {
			for (int i = 0; i < n; i++) {
				sb.append(String.format("%s %02d:%02d %20s %s %d\n", indent, number, i, hex(k(i), 0, 4), leaf ? "==" : "->", c(i)));
				if (! leaf ) {
					long c = c(i);
					Page sub = getPage((int)c);
					sub.toString(sb,indent+" ");
				}
			}
		}

		private String hex(byte[] k, int i, int j) {
			StringBuilder sb = new StringBuilder();
			
			while ( i < j) {
				int b = 0xFF & k[i];
				sb.append(nibble(b>>4));
				sb.append(nibble(b));
				i++;
			}
			return sb.toString();
		}

		private char nibble(int i) {
			i = i & 0xF;
			return (char) ( i >= 10 ? i + 'A' - 10 : i + '0');
		}

	}

	public Index(File file, int keySize) throws IOException {
		capacity = (pageSize - Page.START_OFFSET) / (keySize + valueSize);
		RandomAccessFile raf = new RandomAccessFile(file, "rw");
		this.file = raf.getChannel();
		settings = this.file.map(MapMode.READ_WRITE, 0, pageSize);
		if (this.file.size() == pageSize) {
			this.keySize = keySize;
			settings.putInt(SIGNATURE, MAGIC);
			settings.putInt(KEYSIZE, keySize);
			nextPage = 1;
			root = allocate(true);
			root.n = 1;
			root.set(0, new byte[KEYSIZE], 0);
			root.write();
		} else {
			if (settings.getInt(SIGNATURE) != MAGIC)
				throw new IllegalStateException("No Index file, magic is not " + MAGIC);

			this.keySize = settings.getInt(KEYSIZE);
			if (keySize != 0 && this.keySize != keySize)
				throw new IllegalStateException("Invalid key size for Index file. The file is "
						+ this.keySize + " and was expected to be " + this.keySize);

			root = getPage(1);
			nextPage = (int) (this.file.size() / pageSize);
		}
	}

	public void insert(byte[] k, long v) throws Exception {
		root.insert(k, v);
	}

	public long search(byte[] k) throws Exception {
		return root.search(k);
	}

	Page allocate(boolean leaf) throws IOException {
		Page page = new Page(nextPage++, leaf);
		cache.put(page.number, page);
		return page;
	}

	Page getPage(int number) throws IOException {
		Page page = cache.get(number);
		if (page == null) {
			page = new Page(number);
			cache.put(number, page);
		}
		return page;
	}

	public String toString() {
		return root.toString();
	}
	
	public void close() throws IOException {
		file.close();
		cache.clear();
	}

	public Iterator<byte[]> iterator() {
		return root.iterator();
	}
}
