/*
 *******************************************************************************
 * Copyright (C) 2002-2003, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
 * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/tool/localeconverter/LocaleWriter.java,v $ 
 * $Date: 2003/12/20 03:07:06 $ 
 * $Revision: 1.7 $
 *
 *****************************************************************************************
 */
package com.ibm.icu.dev.tool.localeconverter;

import java.io.*;
import java.util.*;

import com.ibm.icu.impl.UCharacterProperty;

/**
 * A LocaleWriter takes locale data in standard form and
 * writes it to standard output in a form suitable for
 * loading programatically.
 */
public abstract class LocaleWriter {
    private static final String INDENT_CHARS = 
        "                                        "+
        "                                        "+
        "                                        ";
    private static final char EOL_CHARS[] = {'\r', '\n', '\u2028', '\u2029'};
        
    private static final int INDENT_SIZE = 4;
    private static final int MAX_LINE_LENGTH = 80;
    private int indentLevel;
    private String indentString;
    private boolean needsIndent;
    protected StringBuffer lineBuffer = new StringBuffer();
    private int lineLength;
    protected PrintStream out;
    protected PrintStream err;
    //final File outFile = new File(  "cnvLoc.txt");
    //FileOutputStream outFileStream;
    //BufferedWriter outBufWrite;
    //PrintWriter myOut;
    
    public LocaleWriter(PrintStream out) {
        this.out = out;
        this.err = out;
    /*    try{
            outFile.canWrite();
            outFileStream = new FileOutputStream(outFile);
            outBufWrite = new BufferedWriter(new OutputStreamWriter(outFileStream,"UTF8"));                    
        }
        catch(java.io.IOException e){
            System.out.println("Encoding unsupported");
            return;
        }
    */  
    }
    public LocaleWriter(PrintStream out, PrintStream err) {
        this.out = out;
        this.err = err;
        /*
        try{
            outFile.canWrite();
            outFileStream = new FileOutputStream(outFile);
            outBufWrite = new BufferedWriter(new OutputStreamWriter(outFileStream,"UTF8"));                    
        }
        catch(java.io.IOException e){
            System.out.println("Encoding unsupported");
            return;
        }
        */  
    }

    public void write(Locale locale, Hashtable localeData) {
        open(locale);
            //sort the key so the tags are in order in the resource file
        SortedVector order = new SortedVector(localeData.keys(), new SortedVector.StringComparator());
        Enumeration e = order.elements();
        while (e.hasMoreElements()) {
            final String key = (String)e.nextElement();
            final Object data = localeData.get(key);
            if (isDuplicateOfInheritedValue(locale, key, data)) {
               println("///* Discarding duplicate data for tag: "+key+" */");
            } else {
                write(key, data);
            }
        }
       
        close();
    }
    /*
    public void closeFileHandle(){
         try{
            outBufWrite.close();
        }
        catch(java.io.IOException excp){
            out.println("could not close the output file");
        }
    }
    */    
    protected void write(String tag, Object o) {
        if (o instanceof String) {
            write(tag, (String)o);
        } else if (o instanceof String[]) {
            write(tag, (String[]) o);
        } else if (o instanceof String[][]) {
            write(tag, (String[][])o);
        } else if (o instanceof Object[]) {
            Object[] data = (Object[])o;
            String[] temp = new String[data.length];
            for (int i = 0; i < data.length; i++) {
                temp[i] = data[i].toString();
            }
            write(tag, temp);
        } else if (o instanceof Object[][]) {
            Object[][] data = (Object[][])o;
            String[][] temp = new String[data.length][];
            for (int i = 0; i < data.length; i++) {
                temp[i] = new String[data[i].length];
                for (int j = 0; j < temp[i].length; j++) {
                    temp[i][j] = data[i][j].toString();
                }
            }
            write(tag, temp);
        } else {
            write(tag, o.toString());
        }
    }
    protected final void write(String tag, String[][] value) {
        if (value.length > 0) {
            if (value[0].length > 2) {
                write2D(tag, value);
            } else {
                writeTagged(tag, value);
            }
        } else {
            writeTagged(tag, value);
        }
    }

    protected abstract void open(Locale locale);
    protected abstract void write(String tag, String value);
    protected abstract void write(String tag, String[] value);
    protected abstract void write2D(String tag, String[][] value);
    protected abstract void writeTagged(String tag, String[][] value);
    protected abstract void close();
    protected abstract String getStringJoiningCharacter();

    protected void tabTo(int pos) {
        if (pos > lineLength) {
            for (int i = lineLength; i < pos; i++) {
                print(" ");
            }
        }
    }
    /*
    protected void writeToFile(String str){
                
        try{
               outBufWrite.write(prependEsc(str));
        }
        catch(java.io.IOException e){
               out.println("Could not write to file");
        }
    }
    */
    protected void print(String val) {
        if (needsIndent) {
            out.print(indentString);
            //writeToFile(indentString);
            lineLength += indentString.length();
            needsIndent = false;
        }
        String tval = PosixCollationBuilder.unescape(val);
        if(tval.length() < val.length()){
            tval=prependEsc(tval);
        }
        if (tval != null) {
            out.print(prependEsc(tval));
            //writeToFile(tval);
            int len = 0;
            for (int i = 0; i < EOL_CHARS.length; i++) {
                len = Math.max(len, tval.lastIndexOf(EOL_CHARS[i]));
            }
            if (len == 0) {
                lineLength += tval.length();
            } else {
                lineLength = tval.length() - len;
            }
        }
    }
    protected String prependEsc(String str){
        StringBuffer myStr =  new StringBuffer();
        for(int i=0;i<str.length();i++){
            char ch = str.charAt(i);
            if(ch > 0x007f || ch < 0x0020){
                if(ch!=0x0009){
                    myStr.append("\\u");
                    myStr.append(toHexString(ch,16,4));
                }else{
                    myStr.append(ch);
                }
            }
            else{
                myStr.append(ch);
            }
        }
        return myStr.toString();
    }
    protected String toHexString(char ch, int radix, int pad){
        final int MAX_DIGITS = 10;
        int length = 0;
        char buffer[] = new char[10];
        int num = 0;
        int digit;
        int j;
        char temp;
        int i = (int)ch;
        do{
            digit = (int)(i % radix);
            buffer[length++]=(char)(digit<=9?(0x0030+digit):(0x0030+digit+7));
            i=(i/radix);
        }while(i>0);

        while (length < pad){   
            buffer[length++] =  0x0030;/*zero padding */
        }
        /* null terminate the buffer */
        if(length<MAX_DIGITS){
            buffer[length] =  0x0000;
        }
        num= (pad>=length) ? pad :length;
              
        /* Reverses the string */
        for (j = 0; j < (num / 2); j++){
            temp = buffer[(length-1) - j];
            buffer[(length-1) - j] = buffer[j];
            buffer[j] = temp;
            }
        return new String(buffer,0,length);
    }
        
    protected void println(String val) {
        print(val);
        out.println();
        //writeToFile("\n");
        lineLength = 0;
        needsIndent = true;
    }

    protected void printString(String val) {
        if (val != null) {
            indent();
            lineBuffer.setLength(0);
            lineBuffer.append("\"");
            final int size = val.length();
            for (int i = 0; i < size; i++) {
                append(val.charAt(i));
                /*if (!append(val.charAt(i))) {
                        lineBuffer.append("\"");
                        lineBuffer.append(getStringJoiningCharacter());
                        println(lineBuffer.toString());
                        lineBuffer.setLength(0);
                        lineBuffer.append("\"");
                }*/
            }
            
            lineBuffer.append("\"");
            print(lineBuffer.toString());
            outdent();
        } else {
            print("\"\"");
        }
    }
    private boolean isSpecialChar(char ch){
                 
        if(((((ch) <= 0x002F) && ((ch) >= 0x0020)) || 
          (((ch) <= 0x003F) && ((ch) >= 0x003A)) || 
          (((ch) <= 0x0060) && ((ch) >= 0x005B)) || 
          (((ch) <= 0x007E) && ((ch) >= 0x007D)) || 
          (ch) == 0x007B)){
            return true;
          }
          return false;
    }
    protected void printRuleString(String src){
     String val = PosixCollationBuilder.unescape(src);
     if (val != null) {
            indent();
            lineBuffer.setLength(0);
            lineBuffer.append("\"");
            final int size = val.length();
            for (int i = 0; i < size; i++) {
                char ch = val.charAt(i);
                if(ch=='\\'){ //escape char
                    if(((i+1) < val.length())){
                        char c2 = val.charAt(i+1);
                        if(isSpecialChar(c2)){
                            // escape the escape and escape the 
                            // special char
                            append('\\');
                            append('\\');
                            append('\\');
                            append(c2);
                        }else{
                            // write the sequence
                            append('\\');
                            append(c2);
                        }
                    }else{
                       // double escape the escape sequence
                       append('\\');
                       append('\\');
                    }
                    i++;
                }else{
                    if(UCharacterProperty.isRuleWhiteSpace(ch)){
                        append('\\');
                    }
                    
                    append(ch);
                }
 
            }
            
            lineBuffer.append("\"");
            print(lineBuffer.toString());
            outdent();
        } else {
            print("\"\"");
        }
    }
    protected void printUnquotedString(String val) {
         if (val != null) {
             indent();
             lineBuffer.setLength(0);
             //lineBuffer.append("\"");
             final int size = val.length();
             for (int i = 0; i < size; i++) {
                 append(val.charAt(i));
                 /*if (!append(val.charAt(i))) {
                         lineBuffer.append("\"");
                         lineBuffer.append(getStringJoiningCharacter());
                         println(lineBuffer.toString());
                         lineBuffer.setLength(0);
                         lineBuffer.append("\"");
                 }*/
             }
            
             //lineBuffer.append("\"");
             print(lineBuffer.toString());
             outdent();
         } else {
             print("");
         }
     }      
    protected boolean append(final char c) {
        boolean escape = isEscapeChar(c);
        if (escape) {
            appendEscapedChar(c, lineBuffer);
        } else {
            lineBuffer.append(c);
        }
        return (lineLength + lineBuffer.length() < MAX_LINE_LENGTH);
    }
    
    protected boolean isEscapeChar(final char c) {
        switch (c) {
        case '"':
        case '\\':
        case '\n':
        case '\r':
        case '\u2028':
        case '\u2029':
            return true;
        default:
            return (c < ' ') || (c > 0x07F);
        }
    }
    
    protected void appendEscapedChar(char c, StringBuffer buffer) {
        if(c>=0x20 && c < 0x7f){
            buffer.append(c);
        }else{
            buffer.append(getEscapeChar());
            int value = ((int)c) & 0xFFFF;
            buffer.append(HEX_DIGIT[(value & 0xF000) >> 12]);
            buffer.append(HEX_DIGIT[(value & 0x0F00) >> 8]);
            buffer.append(HEX_DIGIT[(value & 0x00F0) >> 4]);
            buffer.append(HEX_DIGIT[(value & 0x000F)]);
        }
    }
    
    protected String getEscapeChar() {
        return "\\u";
    }
    
    protected final void indent() {
        indent(1);
    }
    protected void indent(int amount) {
        indentLevel += amount;
        indentString = INDENT_CHARS.substring(0, indentLevel*INDENT_SIZE);
    }
    
    protected final void outdent() {
        outdent(1);
    }
    protected void outdent(int amount) {
        indentLevel -= amount;
        indentString = INDENT_CHARS.substring(0, indentLevel*INDENT_SIZE);
    }

    static final char[] HEX_DIGIT = {'0','1','2','3','4','5','6','7',
                     '8','9','A','B','C','D','E','F'};

    /** Return true if the value for the specified tag is the same
     * as the value inherited from the parent for that tag */
    private boolean isDuplicateOfInheritedValue(final Locale loc, String tag, Object value) {
        if (value == null) return true;
        try {
            final ResourceBundle parentBundle = getParentBundle(loc);
            if (parentBundle == null) return false;
            Object parentValue = parentBundle.getObject(tag);
            if (!objectsAreEqual(value, parentValue)) {
                return false;
            } else {
                return true;
            }
        } catch (java.util.MissingResourceException e) {
            return false;
        }
    }
    
    private boolean objectsAreEqual(final Object item, final Object parentItem) {
        if (item instanceof Object[] && parentItem instanceof Object[]) {
            return arraysAreEqual((Object[])item, (Object[])parentItem);
        } else {
            return item.equals(parentItem);
        }
    }
    
    private boolean arraysAreEqual(final Object[] item, final Object[] parentItem) {
        boolean matches = item.length == parentItem.length;
        for (int i = 0; i < item.length && matches; i++) {
            matches = objectsAreEqual(item[i], parentItem[i]);
        }
        return matches;
    }
        
    private ResourceBundle getParentBundle(final Locale loc) {
        try {
            final String x = loc.toString();
            final int ndx = x.lastIndexOf('_');
            if (ndx < 0) {
                return null;
            } else {
                final String parentLocName = x.substring(0, ndx);
                final Locale parentLoc = localeFromString(parentLocName);
                return ResourceBundle.getBundle("com.ibm.icu.dev.tool.localeconverter.myLocaleElements", parentLoc);
            }
        } catch (MissingResourceException e) {
            return null;
        }
    }
    
    private String replace(String source, String target, String replacement) {
        if (target.equals(replacement)) {
            return source;
        } else {
            StringBuffer result = new StringBuffer();
            int lastNdx = 0;
            int ndx = source.indexOf(target);
            while (ndx >= 0) {
                result.append(source.substring(lastNdx, ndx));
                result.append(replacement);
                ndx += target.length();
                lastNdx = ndx;
                ndx = source.indexOf(target, ndx);
            }
            result.append(source.substring(lastNdx));
            return result.toString();
        }
    }

    public Locale localeFromString(final String localeName) {
        String language = localeName;
        String country = "";
        String variant = "";
        
        int ndx = language.indexOf('_');
        if (ndx >= 0) {
            country = language.substring(ndx+1);
            language = language.substring(0, ndx);
        }
        ndx = country.indexOf('_');
        if (ndx >= 0) {
            variant = country.substring(ndx);
            country = country.substring(0, ndx);
        }
        return new Locale(language, country, variant);
    }
}
