// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/**
 *******************************************************************************
 * Copyright (C) 2002-2010, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

package com.ibm.icu.dev.tool.layout;

import java.util.Vector;

import com.ibm.icu.text.UTF16;

/**
 * @author Owner
 *
 * To change the template for this generated type comment go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
public class DecompTable implements LookupSubtable
{
    static class DecompEntry
    {
        private int composed;
        private int[] decomp;
        
        DecompEntry(int composedChar, String decomposition)
        {
            int decompCount = UTF16.countCodePoint(decomposition);
            
            composed = composedChar;
            decomp = new int[decompCount];
            
            int out = 0, cp;
            
            for (int in = 0; in < decomposition.length(); in += UTF16.getCharCount(cp)) {
                cp = UTF16.charAt(decomposition, in);
                decomp[out++] = cp;
            }
        }
        
        public int getComposedCharacter()
        {
            return composed;
        }
        
        public int[] getDecomposition()
        {
            return decomp;
        }
        
        public int getDecompositionCount()
        {
            return decomp.length;
        }
        
        public int getDecomposedCharacter(int i)
        {
            if (i >= 0 && i < decomp.length) {
                return decomp[i];
            }
            
            return -1;
        }
        
        public int compareTo(DecompEntry that)
        {
            return this.composed - that.composed;
        }
        
        //
        // Straight insertion sort from Knuth vol. III, pg. 81
        //
        public static void sort(DecompEntry[] table, Vector decompVector)
        {
            for (int j = 0; j < table.length; j += 1) {
                int i;
                DecompEntry v = (DecompEntry) decompVector.elementAt(j);

                for (i = j - 1; i >= 0; i -= 1) {
                    if (v.compareTo(table[i]) >= 0) {
                      break;
                    }

                    table[i + 1] = table[i];
                }

                table[i + 1] = v;
            }
        }
    }
    
    private Vector decompVector;
    private DecompEntry[] decompEntries;
    private int snapshotSize;
    
    public DecompTable()
    {
        decompVector = new Vector();
        decompEntries = null;
        snapshotSize = -1;
    }
    
    public void add(int composed, String decomposition)
    {
        DecompEntry entry = new DecompEntry(composed, decomposition);
        
        decompVector.addElement(entry);
    }
    
    public int getComposedCharacter(int i)
    {
        if (i < 0 || i > decompEntries.length) {
            return -1;
        }
        
        return decompEntries[i].getComposedCharacter();
    }
    
    public int getDecompositionCount(int i)
    {
        if (i < 0 || i > decompEntries.length) {
            return -1;
        }
        
        return decompEntries[i].getDecompositionCount();
    }
    
    public boolean hasEntries()
    {
        return decompVector.size() > 0;
    }
    
    private void snapshot()
    {
        if (snapshotSize != decompVector.size()) {
            snapshotSize = decompVector.size();
            decompEntries = new DecompEntry[snapshotSize];
            DecompEntry.sort(decompEntries, decompVector);
        }
    }

    public void writeLookupSubtable(OpenTypeTableWriter writer)
    {
        snapshot();
        
        int multipleSubstitutionsBase = writer.getOutputIndex();
        int coverageTableIndex, sequenceOffsetIndex;
        int sequenceCount = decompEntries.length;
        
        writer.writeData(1); // format = 1
        
        coverageTableIndex = writer.getOutputIndex();
        writer.writeData(0); // coverage table offset (fixed later)
        
        writer.writeData(sequenceCount);
        
        sequenceOffsetIndex = writer.getOutputIndex();
        for (int s = 0; s < sequenceCount; s += 1) {
            writer.writeData(0); // offset to sequence table (fixed later);
        }
        
        for (int s = 0; s < sequenceCount; s += 1) {
            DecompEntry entry = decompEntries[s];
            int decompCount = entry.getDecompositionCount();
            
            writer.fixOffset(sequenceOffsetIndex++, multipleSubstitutionsBase);
            
            writer.writeData(decompCount); // glyphCount
            
            for (int g = 0; g < decompCount; g += 1) {
                writer.writeData(entry.getDecomposedCharacter(g));
            }
        }
        
        // write a format 1 coverage table
        writer.fixOffset(coverageTableIndex, multipleSubstitutionsBase);
        writer.writeData(1); // format = 1
        writer.writeData(sequenceCount);  // glyphCount
        
        for (int i = 0; i < sequenceCount; i += 1) {
            writer.writeData(decompEntries[i].getComposedCharacter());
        }
    }
}
