/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.eagle.log.entity;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.eagle.log.entity.meta.EntityConstants;
import org.apache.eagle.log.entity.meta.EntityDefinition;
import org.apache.eagle.common.ByteUtil;

public class RowkeyBuilder {
	
	public static final int EMPTY_PARTITION_DEFAULT_HASH_CODE = 0;
	
	/**
	 * Generate the internal sorted hashmap for tags. Please note the partition tags should not be included in the result map.
	 * @param partitions array of partition tags in order
	 * @param tags tags of the entity
	 * @return the sorted hash map of the tags
	 */
	public static SortedMap<Integer, Integer> generateSortedTagMap(String[] partitions, Map<String, String> tags) {
		final SortedMap<Integer, Integer> tagHashMap = new TreeMap<Integer, Integer>();
		for (Map.Entry<String, String> entry: tags.entrySet()) {
			final String tagName = entry.getKey();
			final String tagValue = entry.getValue();
			// If it's a partition tag, we need to remove it from tag hash list. It need to 
			// put to the fix partition hash slot in rowkey.
			if (tagValue == null || isPartitionTag(partitions, tagName))
				continue;
			tagHashMap.put(tagName.hashCode(), tagValue.hashCode());
		}
		return tagHashMap;
	}
	
	/**
	 * build rowkey from InternalLog object
	 * @param log internal log entity to write
	 * @return the rowkey of the entity
	 */
	public static byte[] buildRowkey(InternalLog log) {
		final String[] partitions = log.getPartitions();
		final Map<String, String> tags = log.getTags();
		final SortedMap<Integer, Integer> tagHashMap = generateSortedTagMap(partitions, tags);
		
		// reverse timestamp
		long ts = Long.MAX_VALUE - log.getTimestamp();
		
		List<Integer> partitionHashValues = new ArrayList<Integer>();
		if (partitions != null) {
			for (String partition : partitions) {
				final String tagValue = tags.get(partition);
				if (tagValue != null) {
					partitionHashValues.add(tagValue.hashCode());
				} else {
					partitionHashValues.add(EMPTY_PARTITION_DEFAULT_HASH_CODE);
				}
			}
		}
		return buildRowkey(log.getPrefix().hashCode(), partitionHashValues, ts, tagHashMap);
	}
	
	public static long getTimestamp(byte[] rowkey, EntityDefinition ed) {
		if (!ed.isTimeSeries()) {
			return EntityConstants.FIXED_WRITE_TIMESTAMP;
		}
		final int offset = (ed.getPartitions() == null) ? 4 : (4 + ed.getPartitions().length * 4);
		return Long.MAX_VALUE - ByteUtil.bytesToLong(rowkey, offset);
	}
	
	/**
	 * Check if the tagName is one of the partition tags
	 * @param partitions paritition tags of the entity
	 * @param tagName the tag name that needs to check
	 * @return
	 */
	private static boolean isPartitionTag(String[] partitions, String tagName) {
		if (partitions != null) {
			for (String partition : partitions) {
				if (partition.equals(tagName)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * rowkey is: prefixHash:4 + (partitionValueHash:4)* + timestamp:8 + (tagnameHash:4 + tagvalueHash:4)*
	 * partition fields are sorted by partition definition order, while tag fields are sorted by tag name's 
	 * hash code values. 
	 */
	private static byte[] buildRowkey(int prefixHash, List<Integer> partitionHashValues, long timestamp, SortedMap<Integer, Integer> tags){
		// allocate byte array for rowkey
		final int len = 4 + 8 + tags.size() * (4 + 4) + (partitionHashValues.size() * 4);
		final byte[] rowkey = new byte[len];
		int offset = 0;

		// 1. set prefix
		ByteUtil.intToBytes(prefixHash, rowkey, offset);
		offset += 4;
		
		// 2. set partition
		for (Integer partHash : partitionHashValues) {
			ByteUtil.intToBytes(partHash, rowkey, offset);
			offset += 4;
		}
		
		// 3. set timestamp
		ByteUtil.longToBytes(timestamp, rowkey, offset);
		offset += 8;

		// 4. set tag key/value hashes
		for (Map.Entry<Integer, Integer> entry : tags.entrySet()) {
			ByteUtil.intToBytes(entry.getKey(), rowkey, offset);
			offset += 4;
			ByteUtil.intToBytes(entry.getValue(), rowkey, offset);
			offset += 4;
		}
		
		return rowkey;
	}
}
