/**
 *******************************************************************************
 * Copyright (C) 2001-2003, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
 * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/impl/ICUListResourceBundle.java,v $
 * $Date: 2003/06/03 18:49:32 $
 * $Revision: 1.11 $
 *
 *******************************************************************************
 */

/**
 * 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.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";

    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]);
                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) {

        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]);
                    j++;
                }
                i++;
            }
        }else if(value instanceof Alias){
            String cName = this.getClass().getName();
            visited.clear();
            visited.put(cName+key,"");
            return ((Alias)value).getResource(cName,key,visited);
        }else if(value instanceof RedirectedResource){
            return ((RedirectedResource)value).getResource(this);
        }

        return value;
    }

    private static byte[] readToEOS(InputStream stream) {

        ArrayList vec = new ArrayList();
        int count = 0;
        int pos = 0;
        final int MAXLENGTH = 0x8000; // max buffer size - 32K
        int length = 0x80; // start with small buffers and work up
        do {
            pos = 0;
            length = length >= MAXLENGTH ? MAXLENGTH : length * 2;
            byte[] buffer = new byte[length];
            try {
                do {
                    int n = stream.read(buffer, pos, length - pos);
                    if (n == -1) {
                    break;
                    }
                    pos += n;
                } while (pos < length);
            }
            catch (IOException e) {
            }
            vec.add(buffer);
            count += pos;
        } while (pos == length);


        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;
        }
        return data;
    }

    private static char[] readToEOS(InputStreamReader stream) {
        ArrayList vec = new ArrayList();
        int count = 0;
        int pos = 0;
        final int MAXLENGTH = 0x8000; // max buffer size - 32K
        int length = 0x80; // start with small buffers and work up
        do {
            pos = 0;
            length = length >= MAXLENGTH ? MAXLENGTH : length * 2;
            char[] buffer = new char[length];
            try {
                do {
                    int n = stream.read(buffer, pos, length - pos);
                    if (n == -1) {
                    break;
                    }
                    pos += n;
                } while (pos < length);
            }
            catch (IOException e) {
            }
            vec.add(buffer);
            count += pos;
        } while (pos == length);

        char[] data = new char[count];
        pos = 0;
        for (int i = 0; i < vec.size(); ++i) {
            char[] buf = (char[])vec.get(i);
            int len = Math.min(buf.length, count - pos);
            System.arraycopy(buf, 0, data, pos, len);
            pos += len;
        }
        return data;
    }
    /*
    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=name;
        }
        public Object getResource(Object obj){
            if(expanded==null){
                InputStream stream = obj.getClass().getResourceAsStream(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=name;
        }
        public Object getResource(Object obj){
            if(expanded==null){
                // Resource strings are always UTF-8
                InputStream stream = obj.getClass().getResourceAsStream(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 "";
        }
    }

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


        private Object getResource(String className,String parentKey, 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);
                bundleName=className.substring(j+1,className.indexOf("_"));
                keyPath=pathToResource.substring(i+1);

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

            }

            ResourceBundle bundle = null;
            // getResourceBundle guarantees that the CLASSPATH will be searched
            // for loading the resource with name <bundleName>_<localeName>.class
            bundle = ICULocaleData.getResourceBundle(packageName,bundleName,locale);

            return findResource(bundle,className,keyPath, visited);
        }



        private boolean isIndex(String s){
             if(s.length()==1){
                char c = s.charAt(0);
                return Character.isDigit(c);
             }
             return false;
        }
        private int getIndex(String s){
             if(s.length()==1){
                char c = s.charAt(0);
                if(Character.isDigit(c)){
                  return Integer.valueOf(s).intValue();
                }
             }
             return -1;
        }
        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){
            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);
                }
            }
            return obj;
        }
        private Object findResource(ResourceBundle bundle,String className,String key, Hashtable visited){
            if(key==null){
                return ((ICUListResourceBundle)bundle).getContents();
            }
            if(visited.get(className+key)!=null){
                throw new MissingResourceException("Circular Aliases in bundle.",bundle.getClass().getName(),key);
            }

            visited.put(className+key,"");

            String[] keys = split(key,RES_PATH_SEP_CHAR);
            Object o =null;
            if(keys.length>0){
                o = bundle.getObject(keys[0]);
                o = findResource(o,keys,1);
            }
            o=resolveAliases(o,className,key,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,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((Object)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((Object)o[i],className,key,visited);
                i++;
            }
            return o;
        }

        private 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;
        }
    }

}

