/**
 *******************************************************************************
 * Copyright (C) 2001-2005, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

/**
 * A list resource bundle that does redirection
 * because otherwise some of our resource class files
 * are too big for the java runtime to handle.
 */

package com.ibm.icu.impl;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.ListResourceBundle;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.MissingResourceException;
import java.util.Hashtable;

public class ICUListResourceBundle extends ListResourceBundle {
    private static final String ICUDATA = "ICUDATA";
    private static final String ICU_BUNDLE_NAME = "LocaleElements";
    private static final String ICU_PACKAGE_NAME ="com.ibm.icu.impl.data";
    private static final String ENCODING="UTF-8";

    /* package */ Locale icuLocale;
    /* package */ void setParentX(ResourceBundle b) {
        setParent(b);
    }

    public Locale getLocale() {
        return icuLocale;
    }

    protected ICUListResourceBundle() {
    }

    private Hashtable visited = new Hashtable();
    /**
     * Subclassers must statically initialize this
     */
    protected Object[][] contents;

    /**
     * This is our cache
     */
    private Object[][] realContents;

    /**
     * See base class description
     */
    protected Object[][] getContents(){
        // we replace any redirected values with real values in a cloned array
        if (realContents == null) {
            realContents = contents;
            for (int i = 0; i < contents.length; ++i) {
                Object newValue = getRedirectedResource((String)contents[i][0],contents[i][1], -1);
                if (newValue != null) {
                    if (realContents == contents) {
                        realContents = (Object[][])contents.clone();
                    }
                    realContents[i] = new Object[] { contents[i][0], newValue };
                }
            }
        }
        return realContents;
    }

    /**
     * Return null if value is already in existing contents array, otherwise fetch the
     * real value and return it.
     */
    private Object getRedirectedResource(String key, Object value, int index) {

        if (value instanceof Object[][]) {
            Object[][] aValue = (Object[][])value;
            int i=0;
            while(i < aValue.length){
                int j=0;
                while(j < aValue[i].length){
                    aValue[i][j] = getRedirectedResource((String)aValue[i][0],aValue[i][j], i);
                    j++;
                }
                i++;
            }
        }else if (value instanceof Object[]){
            Object[] aValue = (Object[]) value;
            int i=0;
            while( i < aValue.length){
                aValue[i] = getRedirectedResource(key,aValue[i], i);
                i++;
            }
        }else if(value instanceof Alias){
        
            String cName = this.getClass().getName();
            visited.clear();
            visited.put(cName+key,"");
            return ((Alias)value).getResource(cName,key,index, visited);
        }else if(value instanceof RedirectedResource){
            return ((RedirectedResource)value).getResource(this);
        }

        return value;
    }

    private static byte[] readToEOS(InputStream stream) {
        // As of 3.0 this method reads streams of length 264..274008
        // from the core data.  We progressively double the buffer
        // size to reduce the number of allocations required.
        try {
            ArrayList vec = new ArrayList();
            int count = 0;
            int length = 0x200; // smallest 2^n >= min stream len
            final int MAXLENGTH = 0x8000;
            int pos = -1;
            for (;;) {
                byte[] buffer = new byte[length];
                pos = 0;
                do {
                    int n = stream.read(buffer, pos, length - pos);
                    if (n == -1) {
                        break;
                    }
                    pos += n;
                } while (pos < length);
                count += pos;
                vec.add(buffer);
                if (pos < length) {
                    break;
                }
                if (length < MAXLENGTH) {
                    length <<= 1;
                }
            }

            // System.out.println("\ncount " + count + " bytes from " + stream);

            byte[] data = new byte[count];
            pos = 0;
            for (int i = 0; i < vec.size(); ++i) {
                byte[] buf = (byte[])vec.get(i);
                int len = Math.min(buf.length, count - pos);
                System.arraycopy(buf, 0, data, pos, len);
                pos += len;
            }
            // assert pos==count;
            return data;
        } catch (IOException e) {
            throw new MissingResourceException(e.getMessage(),"","");
        }
    }

    private static char[] readToEOS(InputStreamReader stream) {
        // As of 3.0 this method reads streams of length 41990..41994
        // from the core data.  The IBM 1.4 UTF8 converter doesn't
        // handle buffering reliably (it throws an exception) so we
        // are forced to read everything in one chunk.
        try {
            int length = 0x10000; // smallest 2^n >= max stream len
            final int MAXLENGTH = 0x40000000;
            int n;
            char[] buffer;
            for (;;) {
                buffer = new char[length];
                n = stream.read(buffer, 0, length);
                if (n >= 0 && n < length) {
                    break;
                }
                if (length < MAXLENGTH) {
                    stream.reset();
                    length <<= 1;
                } else {
                    throw new InternalError("maximum input stream length exceeded");
                }
            }

            // System.out.println("\ncount " + n + " chars from " + stream);

            char[] data = new char[n];
            System.arraycopy(buffer, 0, data, 0, n);
            return data;
        } catch (IOException e) {
            throw new MissingResourceException(e.getMessage(),"","");
        }
    }
    /*
    public static class CompressedString implements RedirectedResource{
        private String expanded=null;
        private String compressed=null;
        public CompressedString(String str){
           compressed=str;
        }
        public Object getResource(Object obj){
            if(compressed==null){
                return null;
            }
            if(expanded==null){
                expanded= new String(Utility.RLEStringToCharArray(compressed));
            }
            return expanded;
        }
    }
    */
    public static class CompressedBinary implements RedirectedResource{
        private byte[] expanded=null;
        private String compressed=null;
        public CompressedBinary(String str){
           compressed = str;
        }
        public Object getResource(Object obj){
            if(compressed==null){
                return null;
            }

            if(expanded==null){
                expanded= Utility.RLEStringToByteArray(compressed);
            }
            return expanded;
        }

    }
    private interface RedirectedResource{
        public Object getResource(Object obj);
    }

    public static class ResourceBinary implements RedirectedResource{
        private byte[] expanded=null;
        private String resName=null;
        public ResourceBinary(String name){
            resName="data/" + name;
        }
        public Object getResource(Object obj) {
            if(expanded==null){
                InputStream stream = ICUData.getStream(resName);
                if(stream!=null){
                    //throw new MissingResourceException("",obj.getClass().getName(),resName);
                    expanded = readToEOS(stream);
                    return expanded;
                }
            }
            return "";
        }
    }

    public static class ResourceString implements RedirectedResource{
        private char[] expanded=null;
        private String resName=null;
        public ResourceString(String name){
            resName="data/"+name;
        }
        public Object getResource(Object obj) {
            if(expanded==null){
                // Resource strings are always UTF-8
                InputStream stream = ICUData.getStream(resName);
                if(stream!=null){
                    //throw new MissingResourceException("",obj.getClass().getName(),resName);

                    try{
                        InputStreamReader reader =  new InputStreamReader(stream,ENCODING);
                        expanded = readToEOS(reader);
                    }catch(UnsupportedEncodingException ex){
                        throw new RuntimeException("Could open converter for encoding: " +ENCODING);
                    }
                    return new String(expanded);
                }

            }
            return "";
        }
    }
    
    private static final char RES_PATH_SEP_CHAR = '/';
    
    public static class Alias{
        public Alias(String path){
            pathToResource = path;
        };
        
        private String pathToResource;

        private Object getResource(String className, String parentKey, int index, Hashtable visited){
            String packageName=null,bundleName=null, locale=null, keyPath=null;

            if(pathToResource.indexOf(RES_PATH_SEP_CHAR)==0){
                int i =pathToResource.indexOf(RES_PATH_SEP_CHAR,1);
                int j =pathToResource.indexOf(RES_PATH_SEP_CHAR,i+1);
                bundleName=pathToResource.substring(1,i);
                locale=pathToResource.substring(i+1);
                if(j!=-1){
                    locale=pathToResource.substring(i+1,j);
                    keyPath=pathToResource.substring(j+1,pathToResource.length());
                }
                //there is a path included
                if(bundleName.equals(ICUDATA)){
                    bundleName = ICU_BUNDLE_NAME;
                    packageName = ICU_PACKAGE_NAME;
                }

            }else{
                //no path start with locale
                int i =pathToResource.indexOf(RES_PATH_SEP_CHAR);
                //If this is a bundle with locale name following it
                //then it should be of type <bundle name>_<locale>
                //if not we donot guarantee that this will work
                int j = className.lastIndexOf(".");
                packageName=className.substring(0,j);
                int underScoreIndex = className.indexOf("_");
                if(underScoreIndex>=0){
                    bundleName=className.substring(j+1,className.indexOf("_"));
                }else{
                    bundleName = className.substring(j+1,className.length());
                }
                keyPath=pathToResource.substring(i+1);

                if(i!=-1){
                    locale = pathToResource.substring(0,i);
                }else{
                    locale=keyPath;
                    keyPath=parentKey;
                    if(locale==null || locale.equals("root")){
                        className=packageName+"."+bundleName;
                    }else{
                        className=packageName+"."+bundleName+"_"+ locale;
                    }
                    
                }

            }
            
            ResourceBundle bundle = null;
            // getResourceBundle guarantees that the CLASSPATH will be searched
            // for loading the resource with name <bundleName>_<localeName>.class
            if(locale==null || locale.equals("root")){
                bundle = ICULocaleData.getResourceBundle(packageName,bundleName,"");
            }else{
                bundle = ICULocaleData.getResourceBundle(packageName,bundleName,locale);
            }
            
            return findResource(bundle, className, parentKey, index, keyPath, visited);
        
        }
        
        private Object findResource(Object[][] contents, String key){
            for (int i = 0; i < contents.length; ++i) {
                // key must be non-null String, value must be non-null
                String tempKey = (String) contents[i][0];
                Object value = contents[i][1];
                if (tempKey == null || value == null) {
                    throw new NullPointerException();
                }
                if(tempKey.equals(key)){
                    return value;
                }
            }
            return null;
        }
        
        private Object findResource(Object o , String[] keys, int start, int index){
            Object obj = o;
            if( start < keys.length && keys[start] !=null){
                if(obj instanceof Object[][]){
                    obj = findResource((Object[][])obj,keys[start]);
                }else if(obj instanceof Object[] && isIndex(keys[start])){
                    obj = ((Object[])obj)[getIndex(keys[start])];
                }
                if(start+1 < keys.length && keys[start+1] !=null){
                    obj = findResource(obj,keys,start+1, index);
                }
            }else{
                //try to find the corresponding index resource
                if(index>=0){
                    if(obj instanceof Object[][]){
                        obj = findResource((Object[][])obj,Integer.toString(index));
                    }else if(obj instanceof Object[]){
                        obj = ((Object[])obj)[index];
                    }
                }
            }
            return obj;
        }
        private Object findResource(ResourceBundle bundle, String className, String requestedKey, int index, String aliasKey, Hashtable visited){

            if(aliasKey != null && visited.get(className+aliasKey)!=null){
                throw new MissingResourceException("Circular Aliases in bundle.",bundle.getClass().getName(),requestedKey);
            }
            if(aliasKey==null){
                // currently we do an implicit key lookup
                // return ((ICUListResourceBundle)bundle).getContents();
                aliasKey = requestedKey;
            }
            
            visited.put(className+requestedKey,"");

            String[] keys = split(aliasKey,RES_PATH_SEP_CHAR);
            Object o =null;
            if(keys.length>0){
                o = bundle.getObject(keys[0]);
                o = findResource(o, keys, 1, index);
            }
            o=resolveAliases(o,className,aliasKey,visited);
            return o;
        }
        private  Object resolveAliases(Object o,String className,String key, Hashtable visited){
            if(o instanceof Object[][]){
                o = resolveAliases((Object[][])o,className,key, visited);
            }else if(o instanceof Object[]){
                 o = resolveAliases((Object[])o,className,key, visited);
            }else if(o instanceof Alias){
                return ((Alias)o).getResource(className,key, -1, visited);
            }
            return o;
        }
        private Object resolveAliases(Object[][] o,String className, String key,Hashtable visited){
            int i =0;
            while(i<o.length){
                o[i][1]=resolveAliases(o[i][1],className,key,visited);
                i++;
            }
            return o;
        }
        private Object resolveAliases(Object[] o,String className, String key,Hashtable visited){
            int i =0;
            while(i<o.length){
                o[i]=resolveAliases(o[i],className,key,visited);
                i++;
            }
            return o;
        }


    }
    private static String[] split(String source, char delimiter){

        char[] src = source.toCharArray();
        int index = 0;
        int numdelimit=0;
        // first count the number of delimiters
        for(int i=0;i<source.length();i++){
            if(src[i]==delimiter){
                numdelimit++;
            }
        }
        String[] values =null;
        values = new String[numdelimit+2];
        // now split
        int old=0;
        for(int j=0;j<src.length;j++){
            if(src[j]==delimiter){
                values[index++] = new String(src,old,j-old);
                old=j+1/* skip after the delimiter*/;
            }
        }
        if(old <src.length)
            values[index++]=new String(src,old,src.length-old);
        return values;
    }
    
    /**
     * This method performs multilevel fallback for fetching items from the bundle
     * e.g:
     * If resource is in the form
     * de__PHONEBOOK{
     *      collations{
     *              default{ "phonebook"}
     *      }
     * }
     * If the value of "default" key needs to be accessed, then do:
     * <code>
     *  ResourceBundle bundle = new ResourceBundle(getLocaleFromString("de__PHONEBOOK"));
     *  Object result = null;
     *  if(bundle instanceof ICUListResourceBundle){
     *      result = ((ICUListResourceBundle) bundle).getObjectWithFallback("collations/default");
     *  }
     * </code>
     * @param path  The path to the required resource key
     * @return Object represented by the key
     * @exception MissingResourceException
     */
    public final Object getObjectWithFallback(String path) 
                  throws MissingResourceException{
        String[] keys = split(path, RES_PATH_SEP_CHAR);
        Object result = null;      
        ICUListResourceBundle actualBundle = this;
        
        
        // now recuse to pick up sub levels of the items
        result = findResourceWithFallback(keys, actualBundle);
                    
        if(result == null){
            throw new MissingResourceException("Could not find the resource in ",this.getClass().getName(),path);
        }
        return result;
    }
    

    private Object findResourceWithFallback(String[] keys,
                                            ICUListResourceBundle actualBundle){

        Object obj = null; 
        
        while(actualBundle != null){
            // get the top level resource 
            // getObject is a method on the ResourceBundle class that
            // performs the normal fallback
            obj = actualBundle.getObject(keys[0], actualBundle);
            
            // now find the bundle from the actual bundle 
            // if this bundle does not contain the top level resource,
            // then we can be sure that it does not contain the sub elements
            obj = findResourceWithFallback(obj, keys, 1, 0);
            // did we get the contents? the break
            if(obj != null){
                break;
            }
            // if not try the parent bundle
            actualBundle = (ICUListResourceBundle) actualBundle.parent;
        
        }
        
        return obj;
    }
    private Object findResourceWithFallback(Object o , String[] keys, int start, 
                                            int index){
        Object obj = o;
        
        
            if( start < keys.length && keys[start] !=null){
                if(obj instanceof Object[][]){
                    obj = findResourceWithFallback((Object[][])obj,keys[start]);
                }else if(obj instanceof Object[] && isIndex(keys[start])){
                    obj = ((Object[])obj)[getIndex(keys[start])];
                }
                if(start+1 < keys.length && keys[start+1] !=null){
                    obj = findResourceWithFallback(obj,keys,start+1, index);
                }
            }else{
                //try to find the corresponding index resource
                if(index>=0){
                    if(obj instanceof Object[][]){
                        obj = findResourceWithFallback((Object[][])obj,
                                                        Integer.toString(index));
                    }else if(obj instanceof Object[]){
                        obj = ((Object[])obj)[index];
                    }
                }
            }

        return obj;
    }
    
    private Object findResourceWithFallback(Object[][] cnts, String key){
        Object obj = null;

        for (int i = 0; i < cnts.length; ++i) {
            // key must be non-null String
            String tempKey = (String) cnts[i][0];
            obj = cnts[i][1];
            if(tempKey != null && tempKey.equals(key)){
                return obj;
            }
        }

        return null;
    }
    
    private final Object getObject(String key, 
                                   ICUListResourceBundle actualBundle) {
        Object obj = handleGetObject(key);
        if (obj == null) {
            ICUListResourceBundle p = (ICUListResourceBundle) this.parent;
            while( p!=null){
                obj = p.handleGetObject(key);
                if(obj != null){
                    actualBundle = p;
                    break; 
                }
                p = (ICUListResourceBundle) p.parent;
            }
        }
        return obj;
    }
    private static boolean isIndex(String s){
         if(s.length()==1){
            char c = s.charAt(0);
            return Character.isDigit(c);
         }
         return false;
    }
    private static int getIndex(String s){
         if(s.length()==1){
            char c = s.charAt(0);
            if(Character.isDigit(c)){
              return Integer.valueOf(s).intValue();
            }
         }
         return -1;
    }
}

