/**
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2004 satoshi akabane(akabane@logical-paradox.org)
 *
 */
package org.logical_paradox.fts;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import org.logical_paradox.common.btree.BtreeException;
import org.logical_paradox.common.btree.BtreeKey;

/**
 * FTSのためのキークラス
 * @author satoshi akabane@logical-paradox.org
 */
public class FTSBtreeKey extends BtreeKey {
	// キーのバイトサイズ
	public static final int KEY_BYTE_SIZE = 8 + 8;		// 許容されているキーの長さ + VRM上のオフセット

	private String _key;
	private long _offset;

	/**
	 * コンストラクタ
	 * @param o 引数オブジェクト
	 * @throws BtreeException キーの復元に失敗した
	 */
	public FTSBtreeKey(Object o) throws BtreeException {
		super(o);
	}
	/**
	 * コンストラクタ
	 * @param bstream キーのバイト列
	 * @throws BtreeException バイト列からの復元に失敗した
	 */
	public FTSBtreeKey(byte[] bstream) throws BtreeException {
		super(bstream);
	}
	
	/**
	 * 引数オブジェクトからキーを復元する
	 * @param o 引数オブジェクト
	 */
	protected void objectToBtreeKey(Object o) throws BtreeException {
		_key = ((String)o).trim();
	}

	/**
	 * バイト列からキーを復元する
	 * @param bstream キーのバイト列表現
	 */
	protected void byteStreamToBtreeKey(byte[] bstream) throws BtreeException {
//		ByteBuffer buffer = ByteBuffer.allocate(bstream.length).order(ByteOrder.BIG_ENDIAN);
//		buffer.put(bstream, 0, 8);	//put(bstream);
//		buffer.rewind();

		_offset =
				((long)bstream[7] & 0xff) | 
				(long)(bstream[6] & 0xff) << 8 |
				(long)(bstream[5] & 0xff) << 16 |
				(long)(bstream[4] & 0xff) << 24 |
				(long)(bstream[3] & 0xff) << 32 |
				(long)(bstream[2] & 0xff) << 40 |
				(long)(bstream[1] & 0xff) << 48 |
				(long)(bstream[0] & 0xff) << 56;
//if(_offset != 0) {
//	System.out.println("offset=" + _offset);
//}
//		_offset = buffer.getLong();
//		byte[] strbuf = new byte[bstream.length - 8];
//		buffer.get(strbuf);
//		_key = new String(strbuf).trim();
		_key = new String(bstream, 8, bstream.length - 8).trim();
	}

	/**
	 * キーの文字列表現を返す
	 * @return 文字列表現されたキー
	 */
	public String toString() {
		return _key.toString();
	}

	/**
	 * キーの値が等しいかどうかを返す
	 * @return true;正しい / false:違う
	 */
	public boolean equals(Object obj) {
		if(obj instanceof String) {
			String s = (String)obj;
			return _key.equals(s.trim());
		} else if(obj instanceof BtreeKey) {
			String s = ((BtreeKey)obj).toString().trim();
			return _key.equals(s);
		} else {
			return false;
		}
	}
	/**
	 * VRM上のバイト変位を設定する
	 * @param offset バイト変位
	 */
	public void setOffset(long offset) {
		_offset = offset;
	}
	/**
	 * VRM上のバイト変位を返す
	 * @return バイト変位
	 */
	public long getOffset() {
		return _offset;
	}
	/**
	 * 指定されたキーより小さいかどうかを返す
	 * @param key 比較対象
	 * @return boolean true: this < key / false: this >= key
	 */
	public boolean isLessThan( BtreeKey key ) {
		return _key.compareTo(key.toString().trim()) < 0;
	}

	/**
	 * 指定されたキーより大きいかどうかを返す
	 * @param key 比較対象
	 * @return boolean true: this > key / false: this <= key
	 */
	public boolean isGreaterThan( BtreeKey key ) {
		return _key.compareTo(key.toString().trim()) > 0;
	}

	/**
	 * キーのバイト列表現を返す
	 * @return バイト列
	 */
	public byte[] byteStream() {
		ByteBuffer buffer = ByteBuffer.allocate(FTSBtreeKey.KEY_BYTE_SIZE).order(ByteOrder.BIG_ENDIAN);
		buffer.putLong(_offset);
		buffer.put(_key.getBytes());
		
		return buffer.array();
	}

	/**
	 * このキーのバイトサイズを返す
	 * @return バイトサイズ
	 */
	public int byteSize() {
		return KEY_BYTE_SIZE;
	}
}
