//##header
/*
 *******************************************************************************
 * Copyright (C) 2004-2009, 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;

//#if defined(FOUNDATION10) || defined(J2SE13) || defined(ECLIPSE_FRAGMENT)
//#else
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 handleGetImpl(String indexStr, HashMap table, UResourceBundle requested,
                int[] index, boolean[] isAlias) {
            index[0] = getIndex(indexStr);
            if (index[0] > -1) {
                return handleGetImpl(index[0], table, requested, isAlias);
            }
            throw new UResourceTypeMismatchException("Could not get the correct value for index: "+ index);
        }

        protected UResourceBundle handleGetImpl(int index, HashMap table, UResourceBundle requested,
                boolean[] isAlias) {
            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(Integer.toString(index), itemResource, path, table, requested, this, isAlias);
        }
        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;
            createLookupCache(); // Use bundle cache to access array entries
        }
    }
    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 handleGetImpl(String resKey, HashMap table, UResourceBundle requested,
                int[] index, boolean[] isAlias) {
            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 */
            index[0] = findKey(size, currentOffset, this, resKey);
            if (index[0] == -1) {
                //throw new MissingResourceException(ICUResourceBundleReader.getFullName(baseName, localeID),
                //                                    localeID,
                //                                    key);
                return null;
            }
            currentOffset += getCharOffset(size + (~size & 1))
                    + getIntOffset(index[0]);
            long resOffset = (UNSIGNED_INT_MASK) & ICUResourceBundle.getInt(rawData, currentOffset);
            String path = (isTopLevel == true) ? resKey : resPath + "/" + resKey;

            return createBundleObject(resKey, resOffset, path, table, requested, this, isAlias);
        }

        public int getOffset(int currentOffset, int index) {
            return getChar(rawData, currentOffset + getCharOffset(index));
        }
        protected UResourceBundle handleGetImpl(int index, HashMap table, UResourceBundle requested,
                boolean[] isAlias) {
            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);
            int betterOffset = getOffset(currentOffset, index);
            String itemKey = RES_GET_KEY(rawData, betterOffset).toString();
            currentOffset += getCharOffset(size + (~size & 1))
                    + getIntOffset(index);
            long resOffset = (UNSIGNED_INT_MASK) & ICUResourceBundle.getInt(rawData,currentOffset);
            String path = (isTopLevel == true) ? itemKey : resPath + "/" + itemKey;

            return createBundleObject(itemKey, resOffset, path, table, requested, this, isAlias);
        }
        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 resKey, String resourcePath, long resOffset,
                ICUResourceBundle bundle, boolean topLevel){
            if(bundle!=null){
                assign(this, bundle);
            }
            key = resKey;
            resource = resOffset;
            isTopLevel = topLevel;
            size = countItems();
            resPath = resourcePath;
            createLookupCache(); // Use bundle cache to access nested resources
        }
        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 handleGetImpl(String resKey, HashMap table, UResourceBundle requested,
                int[] index, boolean[] isAlias) {
            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 */
            index[0] = findKey(size, currentOffset, this, resKey);
            if (index[0] == -1) {
                throw new MissingResourceException(
                        "Could not find resource ",
                        ICUResourceBundleReader.getFullName(baseName, localeID),
                        resKey);
            }
            currentOffset += getIntOffset(size) + getIntOffset(index[0]);
            long resOffset = (UNSIGNED_INT_MASK) & ICUResourceBundle.getInt(rawData,currentOffset);
            String path = (isTopLevel == true) ? resKey : resPath + "/" + resKey;

            return createBundleObject(resKey, resOffset, path, table, requested, this, isAlias);
        }

        public int getOffset(int currentOffset, int index) {
            return ICUResourceBundle.getInt(rawData, currentOffset + getIntOffset(index));
        }
        protected UResourceBundle handleGetImpl(int index, HashMap table, UResourceBundle requested,
                boolean[] isAlias) {
            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);
            int betterOffset = getOffset(currentOffset, 0);
            String itemKey = RES_GET_KEY(rawData, betterOffset).toString();
            currentOffset += getIntOffset(size);
            long resOffset = (UNSIGNED_INT_MASK) & ICUResourceBundle.getInt(rawData,currentOffset);
            String path = (isTopLevel == true) ? Integer.toString(index) : resPath + "/" + index;

            return createBundleObject(itemKey, resOffset, path, table, requested, this, isAlias);
        }
        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 resKey, String resourcePath, long resOffset,
                ICUResourceBundle bundle, boolean topLevel){
            if(bundle!=null){
                assign(this, bundle);
            }
            key = resKey;
            resource = resOffset;
            isTopLevel = topLevel;
            size = countItems();
            resPath = resourcePath;
            createLookupCache(); // Use bundle cache to access nested resources
        }
        ResourceTable32(String key, String resPath, long resource,
                ICUResourceBundle bundle, boolean isTopLevel) {
            initialize(key, resPath, resource, bundle, isTopLevel);
        }
    }
}
