/**
 *******************************************************************************
 * Copyright (C) 2001-2002, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
 * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/impl/ICUListResourceBundle.java,v $
 * $Date: 2002/08/13 23:40:52 $
 * $Revision: 1.9 $
 *
 *******************************************************************************
 */

/**
 * 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;
        }
    }
    
    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);
        }
    }
    
    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;
        }
    }
    
}

