//##header
/**
 *******************************************************************************
 * Copyright (C) 2004-2007, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.impl;

import java.util.HashMap;
import java.util.MissingResourceException;

import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;
import com.ibm.icu.util.UResourceBundleIterator;
import com.ibm.icu.util.UResourceTypeMismatchException;

//#ifndef FOUNDATION 
import java.nio.ByteBuffer; 
//#endif 

class ICUResourceBundleImpl {
    
    static final class ResourceArray extends ICUResourceBundle {
        protected String[] handleGetStringArray() {
            String[] strings = new String[size];
            UResourceBundleIterator iter = getIterator();
            int i = 0;
            while (iter.hasNext()) {
                strings[i++] = iter.next().getString();
            }
            return strings;
        }
        /**
         * @internal ICU 3.0
         */
        public String[] getStringArray() {
            return handleGetStringArray();
        }

        protected UResourceBundle handleGet(String index, HashMap table, UResourceBundle requested) {
            int val = getIndex(index);
            if (val > -1) {
                return handleGet(val, table, requested);
            }
            throw new UResourceTypeMismatchException("Could not get the correct value for index: "+ index);
        }

        protected UResourceBundle handleGet(int index, HashMap table, UResourceBundle requested) {
            if (index > size) {
                throw new IndexOutOfBoundsException();
            }
            int offset = RES_GET_OFFSET(resource);
            int itemOffset = offset + getIntOffset(index + 1);
            long itemResource = (UNSIGNED_INT_MASK) & ICUResourceBundle.getInt(rawData,itemOffset);
            String path = (isTopLevel == true) ? Integer.toString(index) : resPath + "/" + index;
            return createBundleObject(null, itemResource, path, table, requested, this);
        }
        private int countItems() {
            int offset = RES_GET_OFFSET(resource);
            int value = getInt(rawData,offset);
            return value;
        }
        ResourceArray(String key, String resPath, long resource, ICUResourceBundle bundle) {
            assign(this, bundle);
            this.resource = resource;
            this.key = key;
            this.size = countItems();
            this.resPath = resPath;
        }
    }
    static final class ResourceBinary extends ICUResourceBundle {
        private byte[] value;
        public ByteBuffer getBinary() {
            return ByteBuffer.wrap(value);
        }      
        public byte [] getBinary(byte []ba) {
            return value;
        }
        private byte[] getValue() {
            int offset = RES_GET_OFFSET(resource);
            int length = ICUResourceBundle.getInt(rawData,offset);
            int byteOffset = offset + getIntOffset(1);
            byte[] dst = new byte[length];
            if (ASSERT) Assert.assrt("byteOffset+length < rawData.length", byteOffset+length < rawData.length);
            System.arraycopy(rawData, byteOffset, dst, 0, length);
            return dst;
        }
        ResourceBinary(String key, String resPath, long resource, ICUResourceBundle bundle) {
            assign(this, bundle);
            this.resource = resource;
            this.key = key;
            this.resPath = resPath;
            value = getValue();
            
        }
    }
    static final class ResourceInt extends ICUResourceBundle {
        public int getInt() {
            return RES_GET_INT(resource);
        }
        public int getUInt() {
            long ret = RES_GET_UINT(resource);
            return (int) ret;
        }
        ResourceInt(String key, String resPath, long resource, ICUResourceBundle bundle) {
            assign(this, bundle);
            this.key = key;
            this.resource = resource;
            this.resPath = resPath;   
        }
    }
    
    static final class ResourceString extends ICUResourceBundle {
        private String value;
        public String getString() {
            return value;
        }
        ResourceString(String key, String resPath, long resource, ICUResourceBundle bundle) {
            assign(this, bundle);
            value = getStringValue(resource);
            this.key = key;
            this.resource = resource;
            this.resPath = resPath;
        }
    }
    
    static final class ResourceIntVector extends ICUResourceBundle {
        private int[] value;
        public int[] getIntVector() {
            return value;
        }
        private int[] getValue() {
            int offset = RES_GET_OFFSET(resource);
            int length = ICUResourceBundle.getInt(rawData,offset);
            int intOffset = offset + getIntOffset(1);
            int[] val = new int[length];
            int byteLength = getIntOffset(length);
            
            if (ASSERT) Assert.assrt("(intOffset+byteLength)<rawData.length", (intOffset+byteLength)<rawData.length);
            
            for(int i=0; i<length;i++){
                val[i]=ICUResourceBundle.getInt(rawData, intOffset+getIntOffset(i));
            }
            return val;
        }
        ResourceIntVector(String key, String resPath, long resource, ICUResourceBundle bundle) {
            assign(this, bundle);
            this.key = key;
            this.resource = resource;
            this.size = 1;
            this.resPath = resPath;
            value = getValue();
        }
    }
    
    static final class ResourceTable extends ICUResourceBundle {

        protected UResourceBundle handleGet(String key, HashMap table, UResourceBundle requested) {
            if(size<=0){
                return null;
            }
            int offset = RES_GET_OFFSET(resource);
            // offset+0 contains number of entries
            // offset+1 contains the keyOffset  
            int currentOffset = (offset) + getCharOffset(1);
            //int keyOffset = rawData.getChar(currentOffset);
            /* do a binary search for the key */
            int foundOffset = findKey(size, currentOffset, this, key);
            if (foundOffset == -1) {
                //throw new MissingResourceException(ICUResourceBundleReader.getFullName(baseName, localeID),
                //                                    localeID,
                //                                    key);
                return null;
            }
            currentOffset += getCharOffset(size + (~size & 1))
                    + getIntOffset(foundOffset);
            long resource = (UNSIGNED_INT_MASK) & ICUResourceBundle.getInt(rawData, currentOffset);
            String path = (isTopLevel == true) ? key : resPath + "/" + key;
            return createBundleObject(key, resource, path, table, requested, this);
        }

        public String getKey(int currentOffset, int index) {
            int charOffset = currentOffset + getCharOffset(index);
            int keyOffset = getChar(rawData,charOffset);
            return RES_GET_KEY(rawData, keyOffset).toString();
        }
        protected UResourceBundle handleGet(int index, HashMap table, UResourceBundle requested) {
            if (index > size) {
                throw new IndexOutOfBoundsException();
            }
            int offset = RES_GET_OFFSET(resource);
            // offset+0 contains number of entries
            // offset+1 contains the keyOffset  
            int currentOffset = (offset) + getCharOffset(1);
            String itemKey = getKey(currentOffset, index);
            currentOffset += getCharOffset(size + (~size & 1))
                    + getIntOffset(index);
            long resource = (UNSIGNED_INT_MASK) & ICUResourceBundle.getInt(rawData,currentOffset);
            String path = (isTopLevel == true)
                    ? Integer.toString(index)
                    : resPath + "/" + index;
            return createBundleObject(itemKey, resource, path, table, requested, this);
        }
        private int countItems() {
            int offset = RES_GET_OFFSET(resource);
            int value = getChar(rawData,offset);
            return value;
        }
        ResourceTable(String key, String resPath, long resource, ICUResourceBundle bundle) {
            this(key, resPath, resource, bundle, false);
        }
        ResourceTable(ICUResourceBundleReader reader, String baseName, String localeID, ClassLoader loader) {

            this.rawData = reader.getData();
            this.rootResource = (UNSIGNED_INT_MASK) & reader.getRootResource();
            this.noFallback = reader.getNoFallback();
            this.baseName = baseName;
            this.localeID = localeID;
            this.ulocale = new ULocale(localeID);
            this.loader = loader;
            initialize(null, "", rootResource, null, isTopLevel);
        }
        void initialize(String key, String resPath, long resource, 
                ICUResourceBundle bundle, boolean isTopLevel){
            if(bundle!=null){
                assign(this, bundle);
            }
            this.key = key;
            this.resource = resource;
            this.isTopLevel = isTopLevel;
            this.size = countItems();
            this.resPath = resPath;
        }
        ResourceTable(String key, String resPath, long resource, 
                ICUResourceBundle bundle, boolean isTopLevel) {
            initialize(key, resPath, resource, bundle, isTopLevel);
        }
    }
    static final class ResourceTable32 extends ICUResourceBundle{

        protected UResourceBundle handleGet(String key, HashMap table, UResourceBundle requested) {
            int offset = RES_GET_OFFSET(resource);
            // offset+0 contains number of entries
            // offset+1 contains the keyOffset  
            int currentOffset = (offset) + getIntOffset(1);
            //int keyOffset = rawData.getChar(currentOffset);
            /* do a binary search for the key */
            int foundOffset = findKey(size, currentOffset, this, key);
            if (foundOffset == -1) {
                throw new MissingResourceException(
                        "Could not find resource ",
                        ICUResourceBundleReader.getFullName(baseName, localeID),
                        key);
            }
            currentOffset += getIntOffset(size) + getIntOffset(foundOffset);
            long resource = (UNSIGNED_INT_MASK) & ICUResourceBundle.getInt(rawData,currentOffset);
            String path = (isTopLevel == true) ? key : resPath + "/" + key;
            return createBundleObject(key, resource, path, table, requested, this);
        }

        public String getKey(int currentOffset, int index) {
            int charOffset = currentOffset + getIntOffset(index);
            int keyOffset = ICUResourceBundle.getInt(rawData,charOffset);
            return RES_GET_KEY(rawData, keyOffset).toString();
        }
        protected UResourceBundle handleGet(int index, HashMap table, UResourceBundle requested) {
            if(size<=0){
                return null;
            }
            if (index > size) {
                throw new IndexOutOfBoundsException();
            }
            int offset = RES_GET_OFFSET(resource);
            // offset+0 contains number of entries
            // offset+1 contains the keyOffset  
            int currentOffset = (offset) + getIntOffset(1)
                    + getIntOffset(index);
            String itemKey = getKey(currentOffset, 0);
            currentOffset += getIntOffset(size);
            long resource = (UNSIGNED_INT_MASK) & ICUResourceBundle.getInt(rawData,currentOffset);
            String path = (isTopLevel == true)
                    ? Integer.toString(index)
                    : resPath + "/" + index;
            return createBundleObject(itemKey, resource, path, table, requested, this);
        }
        private int countItems() {
            int offset = RES_GET_OFFSET(resource);
            int value = ICUResourceBundle.getInt(rawData, offset);
            return value;
        }
        ResourceTable32(String key, String resPath, long resource, ICUResourceBundle bundle) {
            this(key, resPath, resource, bundle, false);
        }
        ResourceTable32(ICUResourceBundleReader reader, String baseName, String localeID, ClassLoader loader) {

            this.rawData = reader.getData();
            this.rootResource = (UNSIGNED_INT_MASK) & reader.getRootResource();
            this.noFallback = reader.getNoFallback();
            this.baseName = baseName;
            this.localeID = localeID;
            this.ulocale = new ULocale(localeID);
            this.loader = loader;
            initialize(null, "", rootResource, null, isTopLevel);
        }
        void initialize(String key, String resPath, long resource, 
                ICUResourceBundle bundle, boolean isTopLevel){
            if(bundle!=null){
                assign(this, bundle);
            }
            this.key = key;
            this.resource = resource;
            this.isTopLevel = isTopLevel;
            this.size = countItems();
            this.resPath = resPath;
            
        }
        ResourceTable32(String key, String resPath, long resource, 
                ICUResourceBundle bundle, boolean isTopLevel) {
            initialize(key, resPath, resource, bundle, isTopLevel);
        }
    }
}
