/*
 **********************************************************************
 * Copyright (c) 2002-2015, International Business Machines
 * Corporation and others.  All Rights Reserved.
 **********************************************************************
 * Author: Alan Liu
 * Created: November 5 2002
 * Since: ICU 2.4
 * 2010nov19 Markus Scherer  Rewrite for formatVersion 2.
 **********************************************************************
 */

package com.ibm.icu.impl;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.MissingResourceException;

import com.ibm.icu.lang.UProperty;
import com.ibm.icu.util.BytesTrie;

/**
 * Wrapper for the pnames.icu binary data file.  This data file is
 * imported from icu4c.  It contains property and property value
 * aliases from the UCD files PropertyAliases.txt and
 * PropertyValueAliases.txt.  The file is built by the icu4c tool
 * genpname.  It must be an ASCII big-endian file to be
 * usable in icu4j.
 *
 * This class performs two functions.
 *
 * (1) It can import the flat binary data into usable objects.
 *
 * (2) It provides an API to access the tree of objects.
 *
 * Needless to say, this class is tightly coupled to the binary format
 * of icu4c's pnames.icu file.
 *
 * Each time a UPropertyAliases is constructed, the pnames.icu file is
 * read, parsed, and data structures assembled.  Clients should create one
 * singleton instance and cache it.
 *
 * @author Alan Liu
 * @since ICU 2.4
 */
public final class UPropertyAliases {
    // Byte offsets from the start of the data, after the generic header.
    private static final int IX_VALUE_MAPS_OFFSET=0;
    private static final int IX_BYTE_TRIES_OFFSET=1;
    private static final int IX_NAME_GROUPS_OFFSET=2;
    private static final int IX_RESERVED3_OFFSET=3;
    // private static final int IX_RESERVED4_OFFSET=4;
    // private static final int IX_TOTAL_SIZE=5;

    // Other values.
    // private static final int IX_MAX_NAME_LENGTH=6;
    // private static final int IX_RESERVED7=7;
    // private static final int IX_COUNT=8;

    //----------------------------------------------------------------
    // Runtime data.  This is an unflattened representation of the
    // data in pnames.icu.

    private int[] valueMaps;
    private byte[] bytesTries;
    private String nameGroups;

    private static final class IsAcceptable implements ICUBinary.Authenticate {
        // @Override when we switch to Java 6
        public boolean isDataVersionAcceptable(byte version[]) {
            return version[0]==2;
        }
    }
    private static final IsAcceptable IS_ACCEPTABLE=new IsAcceptable();
    private static final int DATA_FORMAT=0x706E616D;  // "pnam"

    private void load(ByteBuffer bytes) throws IOException {
        //dataVersion=ICUBinary.readHeaderAndDataVersion(bytes, DATA_FORMAT, IS_ACCEPTABLE);
        ICUBinary.readHeader(bytes, DATA_FORMAT, IS_ACCEPTABLE);
        int indexesLength=bytes.getInt()/4;  // inIndexes[IX_VALUE_MAPS_OFFSET]/4
        if(indexesLength<8) {  // formatVersion 2 initially has 8 indexes
            throw new IOException("pnames.icu: not enough indexes");
        }
        int[] inIndexes=new int[indexesLength];
        inIndexes[0]=indexesLength*4;
        for(int i=1; i<indexesLength; ++i) {
            inIndexes[i]=bytes.getInt();
        }

        // Read the valueMaps.
        int offset=inIndexes[IX_VALUE_MAPS_OFFSET];
        int nextOffset=inIndexes[IX_BYTE_TRIES_OFFSET];
        int numInts=(nextOffset-offset)/4;
        valueMaps=ICUBinary.getInts(bytes, numInts, 0);

        // Read the bytesTries.
        offset=nextOffset;
        nextOffset=inIndexes[IX_NAME_GROUPS_OFFSET];
        int numBytes=nextOffset-offset;
        bytesTries=new byte[numBytes];
        bytes.get(bytesTries);

        // Read the nameGroups and turn them from ASCII bytes into a Java String.
        offset=nextOffset;
        nextOffset=inIndexes[IX_RESERVED3_OFFSET];
        numBytes=nextOffset-offset;
        StringBuilder sb=new StringBuilder(numBytes);
        for(int i=0; i<numBytes; ++i) {
            sb.append((char)bytes.get());
        }
        nameGroups=sb.toString();
    }

    private UPropertyAliases() throws IOException {
        ByteBuffer bytes = ICUBinary.getRequiredData("pnames.icu");
        load(bytes);
    }

    private int findProperty(int property) {
        int i=1;  // valueMaps index, initially after numRanges
        for(int numRanges=valueMaps[0]; numRanges>0; --numRanges) {
            // Read and skip the start and limit of this range.
            int start=valueMaps[i];
            int limit=valueMaps[i+1];
            i+=2;
            if(property<start) {
                break;
            }
            if(property<limit) {
                return i+(property-start)*2;
            }
            i+=(limit-start)*2;  // Skip all entries for this range.
        }
        return 0;
    }

    private int findPropertyValueNameGroup(int valueMapIndex, int value) {
        if(valueMapIndex==0) {
            return 0;  // The property does not have named values.
        }
        ++valueMapIndex;  // Skip the BytesTrie offset.
        int numRanges=valueMaps[valueMapIndex++];
        if(numRanges<0x10) {
            // Ranges of values.
            for(; numRanges>0; --numRanges) {
                // Read and skip the start and limit of this range.
                int start=valueMaps[valueMapIndex];
                int limit=valueMaps[valueMapIndex+1];
                valueMapIndex+=2;
                if(value<start) {
                    break;
                }
                if(value<limit) {
                    return valueMaps[valueMapIndex+value-start];
                }
                valueMapIndex+=limit-start;  // Skip all entries for this range.
            }
        } else {
            // List of values.
            int valuesStart=valueMapIndex;
            int nameGroupOffsetsStart=valueMapIndex+numRanges-0x10;
            do {
                int v=valueMaps[valueMapIndex];
                if(value<v) {
                    break;
                }
                if(value==v) {
                    return valueMaps[nameGroupOffsetsStart+valueMapIndex-valuesStart];
                }
            } while(++valueMapIndex<nameGroupOffsetsStart);
        }
        return 0;
    }

    private String getName(int nameGroupsIndex, int nameIndex) {
        int numNames=nameGroups.charAt(nameGroupsIndex++);
        if(nameIndex<0 || numNames<=nameIndex) {
            throw new IllegalIcuArgumentException("Invalid property (value) name choice");
        }
        // Skip nameIndex names.
        for(; nameIndex>0; --nameIndex) {
            while(0!=nameGroups.charAt(nameGroupsIndex++)) {}
        }
        // Find the end of this name.
        int nameStart=nameGroupsIndex;
        while(0!=nameGroups.charAt(nameGroupsIndex)) {
            ++nameGroupsIndex;            
        }
        if(nameStart==nameGroupsIndex) {
            return null;  // no name (Property[Value]Aliases.txt has "n/a")
        }
        return nameGroups.substring(nameStart, nameGroupsIndex);
    }

    private static int asciiToLowercase(int c) {
        return 'A'<=c && c<='Z' ? c+0x20 : c;
    }

    private boolean containsName(BytesTrie trie, CharSequence name) {
        BytesTrie.Result result=BytesTrie.Result.NO_VALUE;
        for(int i=0; i<name.length(); ++i) {
            int c=name.charAt(i);
            // Ignore delimiters '-', '_', and ASCII White_Space.
            if(c=='-' || c=='_' || c==' ' || (0x09<=c && c<=0x0d)) {
                continue;
            }
            if(!result.hasNext()) {
                return false;
            }
            c=asciiToLowercase(c);
            result=trie.next(c);
        }
        return result.hasValue();
    }

    //----------------------------------------------------------------
    // Public API

    public static final UPropertyAliases INSTANCE;

    static {
        try {
            INSTANCE = new UPropertyAliases();
        } catch(IOException e) {
            ///CLOVER:OFF
            MissingResourceException mre = new MissingResourceException(
                    "Could not construct UPropertyAliases. Missing pnames.icu", "", "");
            mre.initCause(e);
            throw mre;
            ///CLOVER:ON
        }
    }

    /**
     * Returns a property name given a property enum.
     * Multiple names may be available for each property;
     * the nameChoice selects among them.
     */
    public String getPropertyName(int property, int nameChoice) {
        int valueMapIndex=findProperty(property);
        if(valueMapIndex==0) {
            throw new IllegalArgumentException(
                    "Invalid property enum "+property+" (0x"+Integer.toHexString(property)+")");
        }
        return getName(valueMaps[valueMapIndex], nameChoice);
    }

    /**
     * Returns a value name given a property enum and a value enum.
     * Multiple names may be available for each value;
     * the nameChoice selects among them.
     */
    public String getPropertyValueName(int property, int value, int nameChoice) {
        int valueMapIndex=findProperty(property);
        if(valueMapIndex==0) {
            throw new IllegalArgumentException(
                    "Invalid property enum "+property+" (0x"+Integer.toHexString(property)+")");
        }
        int nameGroupOffset=findPropertyValueNameGroup(valueMaps[valueMapIndex+1], value);
        if(nameGroupOffset==0) {
            throw new IllegalArgumentException(
                    "Property "+property+" (0x"+Integer.toHexString(property)+
                    ") does not have named values");
        }
        return getName(nameGroupOffset, nameChoice);
    }

    private int getPropertyOrValueEnum(int bytesTrieOffset, CharSequence alias) {
        BytesTrie trie=new BytesTrie(bytesTries, bytesTrieOffset);
        if(containsName(trie, alias)) {
            return trie.getValue();
        } else {
            return UProperty.UNDEFINED;
        }
    }

    /**
     * Returns a property enum given one of its property names.
     * If the property name is not known, this method returns
     * UProperty.UNDEFINED.
     */
    public int getPropertyEnum(CharSequence alias) {
        return getPropertyOrValueEnum(0, alias);
    }

    /**
     * Returns a value enum given a property enum and one of its value names.
     */
    public int getPropertyValueEnum(int property, CharSequence alias) {
        int valueMapIndex=findProperty(property);
        if(valueMapIndex==0) {
            throw new IllegalArgumentException(
                    "Invalid property enum "+property+" (0x"+Integer.toHexString(property)+")");
        }
        valueMapIndex=valueMaps[valueMapIndex+1];
        if(valueMapIndex==0) {
            throw new IllegalArgumentException(
                    "Property "+property+" (0x"+Integer.toHexString(property)+
                    ") does not have named values");
        }
        // valueMapIndex is the start of the property's valueMap,
        // where the first word is the BytesTrie offset.
        return getPropertyOrValueEnum(valueMaps[valueMapIndex], alias);
    }

    /**
     * Returns a value enum given a property enum and one of its value names. Does not throw.
     * @return value enum, or UProperty.UNDEFINED if not defined for that property
     */
    public int getPropertyValueEnumNoThrow(int property, CharSequence alias) {
        int valueMapIndex=findProperty(property);
        if(valueMapIndex==0) {
            return UProperty.UNDEFINED;
        }
        valueMapIndex=valueMaps[valueMapIndex+1];
        if(valueMapIndex==0) {
            return UProperty.UNDEFINED;
        }
        // valueMapIndex is the start of the property's valueMap,
        // where the first word is the BytesTrie offset.
        return getPropertyOrValueEnum(valueMaps[valueMapIndex], alias);
    }

    /**
     * Compare two property names, returning <0, 0, or >0.  The
     * comparison is that described as "loose" matching in the
     * Property*Aliases.txt files.
     */
    public static int compare(String stra, String strb) {
        // Note: This implementation is a literal copy of
        // uprv_comparePropertyNames.  It can probably be improved.
        int istra=0, istrb=0, rc;
        int cstra=0, cstrb=0;
        for (;;) {
            /* Ignore delimiters '-', '_', and ASCII White_Space */
            while (istra<stra.length()) {
                cstra = stra.charAt(istra);
                switch (cstra) {
                case '-':  case '_':  case ' ':  case '\t':
                case '\n': case 0xb/*\v*/: case '\f': case '\r':
                    ++istra;
                    continue;
                }
                break;
            }

            while (istrb<strb.length()) {
                cstrb = strb.charAt(istrb);
                switch (cstrb) {
                case '-':  case '_':  case ' ':  case '\t':
                case '\n': case 0xb/*\v*/: case '\f': case '\r':
                    ++istrb;
                    continue;
                }
                break;
            }

            /* If we reach the ends of both strings then they match */
            boolean endstra = istra==stra.length();
            boolean endstrb = istrb==strb.length();
            if (endstra) {
                if (endstrb) return 0;
                cstra = 0;
            } else if (endstrb) {
                cstrb = 0;
            }

            rc = asciiToLowercase(cstra) - asciiToLowercase(cstrb);
            if (rc != 0) {
                return rc;
            }

            ++istra;
            ++istrb;
        }
    }
}
