// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
 *******************************************************************************
 * Copyright (C) 1998-2008, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
 * Created on Dec 09, 2003
 *
 *******************************************************************************
 */
package com.ibm.icu.dev.tool.layout;

import java.io.PrintStream;
import java.util.Vector;

public class ThaiStateTable
{
    static Vector stateTable = null;
    static int nextState = 0;
    
    private final static int newState()
    {
        ThaiStateTransition[] stateRow = new ThaiStateTransition[ThaiCharacterClasses.cCount];
        
        for (int c = 0; c < ThaiCharacterClasses.cCount; c += 1) {
            stateRow[c] = null;
        }
        
        stateTable.addElement(stateRow);
        
        return nextState++;
    }
    
    private final static boolean isLegalHere(int state, char pairAction)
    {
        switch (pairAction) {
        case 'A':
            return state == 0;
            
        case 'C':
        case 'D':
        case 'E':
        case 'F':
        case 'G':
        case 'H':
            return true;
        
        case 'R':
        case 'S':
            return false;
        }
        
        return false;
    }
    
    private final static boolean composesWithAnything(int charClass)
    {
        for (int c = 0; c < ThaiCharacterClasses.cCount; c += 1) {
            char action = ThaiCharacterClasses.getPairAction(charClass, c);
            
            if (action >= 'C' && action <= 'I') {
                return true;
            }
        }
        
        return false;
    }
    
    private final static void fixNextStates()
    {
        ThaiStateTransition[] groundState = (ThaiStateTransition[]) stateTable.elementAt(0);
        
        for (int s = 1; s < stateTable.size(); s += 1) {
            ThaiStateTransition[] state = (ThaiStateTransition[]) stateTable.elementAt(s);
            
            for (int c = 0; c < ThaiCharacterClasses.cCount; c += 1) {
                ThaiStateTransition transition = state[c];
                
                if (transition.getNextState() == 0) {
                    transition.setNextState(groundState[c].getNextState());
                }
            }
        }
    }
    
    private final static int addState(int prevClass, int prevPrevClass)
    {
        int state = newState();
        ThaiStateTransition[] stateRow = (ThaiStateTransition[]) stateTable.elementAt(state);
        
        for (int c = 0; c < ThaiCharacterClasses.cCount; c += 1) {
            char pairAction = ThaiCharacterClasses.getPairAction(prevClass, c);
            int nextSt = 0;
            
            switch (pairAction) {
            case 'G':
                if (prevClass == ThaiCharacterClasses.NIK &&
                    prevPrevClass == ThaiCharacterClasses.AV1) {
                    pairAction = 'R';
                } else if (prevPrevClass != ThaiCharacterClasses.COA) {
                    pairAction = 'C';
                }
                break;
                
            case 'E':
                if (prevPrevClass == ThaiCharacterClasses.COA) {
                    pairAction = 'F';
                }
                break;
                
            case 'I':
                if (prevClass == ThaiCharacterClasses.TON &&
                    (prevPrevClass < ThaiCharacterClasses.CON ||
                     prevPrevClass > ThaiCharacterClasses.COD)) {
                    pairAction = 'S';
                } else {
                    pairAction = 'A';
                }
                break;
                
            default:
                break;
            }
            
            if (c != prevClass && isLegalHere(state, pairAction) && composesWithAnything(c)) {
                nextSt = addState(c, prevClass);
            }
            
            stateRow[c] = new ThaiStateTransition(nextSt, pairAction);
        }
        
        return state;
    }
    
    static
    {
        stateTable = new Vector();
            
        addState(ThaiCharacterClasses.NON, ThaiCharacterClasses.NON);
            
        fixNextStates();
    }
    
    public static ThaiStateTransition getTransition(int state, int currClass)
    {
        ThaiStateTransition[] row = (ThaiStateTransition[]) stateTable.elementAt(state);
        
        return row[currClass];
    }

    private static String header0 =
"const ThaiShaping::StateTransition ThaiShaping::thaiStateTable[][ThaiShaping::classCount] = {";

    private static String header1 =
"    //+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+";

    private static String header2 =
"    //|         N         C         C         C         L         F         F         F         B         B         B         T         A         A         A         N         A         A         A    |\n" +
"    //|         O         O         O         O         V         V         V         V         V         V         D         O         D         D         D         I         V         V         V    |\n" +
"    //|         N         N         A         D         O         1         2         3         1         2         I         N         1         2         3         K         1         2         3    |";
    
    public static void writeStateTable(PrintStream output)
    {
        System.out.print("Writing state table...");
        
        output.println(header0);
        output.println(header1);
        output.println(header2);
        output.println(header1);
        
        for (int state = 0; state < stateTable.size(); state += 1) {
            ThaiStateTransition[] row = (ThaiStateTransition[]) stateTable.elementAt(state);
            
            output.print("    /*");
            
            if (state < 10) {
                output.print("0");
            }
            
            output.print(state);
            
            output.print("*/ {");
            
            for (int c = 0; c < ThaiCharacterClasses.cCount; c += 1) {
                row[c].write(output);
                
                if (c < ThaiCharacterClasses.cCount - 1) {
                    output.print(", ");
                }
            }
            
            output.print("}");
                    
            if (state < stateTable.size() - 1) {
                output.print(",");
            }
                    
            output.println();
        }
        
        output.println("};\n");
        
        System.out.println(" done.");
    }
}
