//##header
/*
 **********************************************************************
 * Copyright (c) 2006-2009, International Business Machines
 * Corporation and others.  All Rights Reserved.
 **********************************************************************
 * Created on 2006-4-21
 */
package com.ibm.icu.dev.test;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.NoSuchElementException;

import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.util.UResourceBundle;
import com.ibm.icu.util.UResourceBundleIterator;
import com.ibm.icu.util.UResourceTypeMismatchException;

/**
 * Represents a collection of test data described in a UResourceBoundle file. 
 * 
 * The root of the UResourceBoundle file is a table resource, and it has one 
 * Info and one TestData sub-resources. The Info describes the data module
 * itself. The TestData, which is a table resource, has a collection of test 
 * data.
 * 
 * The test data is a named table resource which has Info, Settings, Headers,
 * and Cases sub-resources. 
 * 
 * <pre>
 * DataModule:table(nofallback){ 
 *   Info:table {} 
 *   TestData:table {
 *     entry_name:table{
 *       Info:table{}
 *       Settings:array{}
 *       Headers:array{}
 *       Cases:array{}
 *     }
 *   } 
 * }
 * </pre>
 * 
 * The test data is expected to be fed to test code by following sequence 
 *
 *   for each setting in Setting{
 *       prepare the setting
 *     for each test data in Cases{
 *       perform the test
 *     }
 *   }
 * 
 * For detail of the specification, please refer to the code. The code is 
 * initially ported from "icu4c/source/tools/ctestfw/unicode/tstdtmod.h"
 * and should be maintained parallelly.
 * 
 * @author Raymond Yang
 */
class ResourceModule implements TestDataModule {
    private static final String INFO = "Info";
//    private static final String DESCRIPTION = "Description";
//    private static final String LONG_DESCRIPTION = "LongDescription";
    private static final String TEST_DATA = "TestData";
    private static final String SETTINGS = "Settings";
    private static final String HEADER = "Headers";
    private static final String DATA = "Cases";

    
    UResourceBundle res;
    UResourceBundle info;
    UResourceBundle defaultHeader;
    UResourceBundle testData;
    
    ResourceModule(String baseName, String localeName) throws DataModuleFormatError{

        res = (UResourceBundle) UResourceBundle.getBundleInstance(baseName, localeName);
        info = getFromTable(res, INFO, UResourceBundle.TABLE);
        testData = getFromTable(res, TEST_DATA, UResourceBundle.TABLE);

        try {
            // unfortunately, actually, data can be either ARRAY or STRING
            defaultHeader = getFromTable(info, HEADER, new int[]{UResourceBundle.ARRAY, UResourceBundle.STRING});
        } catch (MissingResourceException e){
            defaultHeader = null;
        }
    }

    public String getName() {
        return res.getKey();
    }

    public DataMap getInfo() {
        return new UTableResource(info);
    }

    public TestData getTestData(String testName) throws DataModuleFormatError {
        return new UResourceTestData(defaultHeader, testData.get(testName));
    }

    public Iterator getTestDataIterator() {
        return new IteratorAdapter(testData){
            protected Object prepareNext(UResourceBundle nextRes) throws DataModuleFormatError {
                return new UResourceTestData(defaultHeader, nextRes);
            }
        };
    }

    /**
     * To make UResourceBundleIterator works like Iterator
     * and return various data-driven test object for next() call
     * 
     * @author Raymond Yang
     */
    private abstract static class IteratorAdapter implements Iterator{
        private UResourceBundle res;
        private UResourceBundleIterator itr;
        private Object preparedNextElement = null;
        // fix a strange behavior for UResourceBundleIterator for 
        // UResourceBundle.STRING. It support hasNext(), but does 
        // not support next() now. 
        // 
        // Use the iterated resource itself as the result from next() call
        private boolean isStrRes = false;
        private boolean isStrResPrepared = false; // for STRING resouce, we only prepare once

        IteratorAdapter(UResourceBundle theRes) {
            assert_not (theRes == null);
            res = theRes;
            itr = ((ICUResourceBundle)res).getIterator();
            isStrRes = res.getType() == UResourceBundle.STRING;
        }
        
        public void remove() {
            // do nothing
        }

        private boolean hasNextForStrRes(){
            assert_is (isStrRes);
            assert_not (!isStrResPrepared && preparedNextElement != null);
            if (isStrResPrepared && preparedNextElement != null) return true;
            if (isStrResPrepared && preparedNextElement == null) return false; // only prepare once
            assert_is (!isStrResPrepared && preparedNextElement == null);
            
            try {
                preparedNextElement = prepareNext(res);
                assert_not (preparedNextElement == null, "prepareNext() should not return null");
                isStrResPrepared = true; // toggle the tag
                return true;
            } catch (DataModuleFormatError e) {
//#if defined(FOUNDATION10) || defined(J2SE13)
//##                throw new RuntimeException(e.getMessage());
//#else
                throw new RuntimeException(e.getMessage(),e);
//#endif
            }            
        }
        public boolean hasNext() {
            if (isStrRes) return hasNextForStrRes();
            
            if (preparedNextElement != null) return true;
            UResourceBundle t = null;
            if (itr.hasNext()) {
                // Notice, other RuntimeException may be throwed
                t = itr.next();
            } else {
                return false;
            }

            try {
                preparedNextElement = prepareNext(t);
                assert_not (preparedNextElement == null, "prepareNext() should not return null");
                return true;
            } catch (DataModuleFormatError e) {
                // Sadly, we throw RuntimeException also
//#if defined(FOUNDATION10) || defined(J2SE13)
//##                throw new RuntimeException(e.getMessage());
//#else
                throw new RuntimeException(e.getMessage(),e);
//#endif
            }
        }

        public Object next(){
            if (hasNext()) {
                Object t = preparedNextElement;
                preparedNextElement = null;
                return t;
            } else {
                throw new NoSuchElementException();
            }
        }
        /**
         * To prepare data-driven test object for next() call, should not return null
         */
        abstract protected Object prepareNext(UResourceBundle nextRes) throws DataModuleFormatError;
    }
    
    
    /**
     * Avoid use Java 1.4 language new assert keyword 
     */
    static void assert_is(boolean eq, String msg){
        if (!eq) throw new Error("test code itself has error: " + msg);
    }
    static void assert_is(boolean eq){
        if (!eq) throw new Error("test code itself has error.");
    }
    static void assert_not(boolean eq, String msg){
        assert_is(!eq, msg);
    }
    static void assert_not(boolean eq){
        assert_is(!eq);
    }
            
    /**
     * Internal helper function to get resource with following add-on 
     * 
     * 1. Assert the returned resource is never null.
     * 2. Check the type of resource. 
     * 
     * The UResourceTypeMismatchException for various get() method is a 
     * RuntimeException which can be silently bypassed. This behavior is a 
     * trouble. One purpose of the class is to enforce format checking for 
     * resource file. We don't want to the exceptions are silently bypassed 
     * and spreaded to our customer's code. 
     * 
     * Notice, the MissingResourceException for get() method is also a
     * RuntimeException. The caller functions should avoid sepread the execption
     * silently also. The behavior is modified because some resource are 
     * optional and can be missed.
     */
    static UResourceBundle getFromTable(UResourceBundle res, String key, int expResType) throws DataModuleFormatError{
        return getFromTable(res, key, new int[]{expResType});
    }
    
    static UResourceBundle getFromTable(UResourceBundle res, String key, int[] expResTypes) throws DataModuleFormatError{
        assert_is (res != null && key != null && res.getType() == UResourceBundle.TABLE);
        UResourceBundle t = res.get(key); 
      
        assert_not (t ==null);
        int type = t.getType();
        Arrays.sort(expResTypes);
        if (Arrays.binarySearch(expResTypes, type) >= 0) {
            return t;
        } else {
//#if defined(FOUNDATION10) || defined(J2SE13)
//##            throw new DataModuleFormatError("Actual type " + t.getType() + " != expected types " + expResTypes + ".");
//#else
            throw new DataModuleFormatError(new UResourceTypeMismatchException("Actual type " + t.getType() + " != expected types " + expResTypes + "."));
//#endif
        }
    }
    
    /**
     * Unfortunately, UResourceBundle is unable to treat one string as string array.
     * This function return a String[] from UResourceBundle, regardless it is an array or a string 
     */
    static String[] getStringArrayHelper(UResourceBundle res, String key) throws DataModuleFormatError{
        UResourceBundle t = getFromTable(res, key, new int[]{UResourceBundle.ARRAY, UResourceBundle.STRING});
        return getStringArrayHelper(t);
    }

    static String[] getStringArrayHelper(UResourceBundle res) throws DataModuleFormatError{
        try{
            int type = res.getType();
            switch (type) {
            case UResourceBundle.ARRAY:
                return res.getStringArray();
            case UResourceBundle.STRING:
                return new String[]{res.getString()};
            default:
                throw new UResourceTypeMismatchException("Only accept ARRAY and STRING types.");
            }
        } catch (UResourceTypeMismatchException e){
//#if defined(FOUNDATION10) || defined(J2SE13)
//##            throw new DataModuleFormatError(e.getMessage());
//#else
            throw new DataModuleFormatError(e);
//#endif
        }
    }
    
    public static void main(String[] args){
        try {
            TestDataModule m = new ResourceModule("com/ibm/icu/dev/data/testdata/","DataDrivenCollationTest");
        System.out.println("hello: " + m.getName());
        m.getInfo();
        m.getTestDataIterator();
        } catch (DataModuleFormatError e) {
            // TODO Auto-generated catch block
            System.out.println("???");
            e.printStackTrace();
        }
    }

    private static class UResourceTestData implements TestData{
        private UResourceBundle res;
        private UResourceBundle info;
        private UResourceBundle settings; 
        private UResourceBundle header;
        private UResourceBundle data;

        UResourceTestData(UResourceBundle defaultHeader, UResourceBundle theRes) throws DataModuleFormatError{
            
            assert_is (theRes != null && theRes.getType() == UResourceBundle.TABLE);
            res = theRes;
            // unfortunately, actually, data can be either ARRAY or STRING
            data = getFromTable(res, DATA, new int[]{UResourceBundle.ARRAY, UResourceBundle.STRING});
       

            
            try {
                // unfortunately, actually, data can be either ARRAY or STRING
                header = getFromTable(res, HEADER, new int[]{UResourceBundle.ARRAY, UResourceBundle.STRING});
            } catch (MissingResourceException e){
                if (defaultHeader == null) {
                    throw new DataModuleFormatError("Unable to find a header for test data '" + res.getKey() + "' and no default header exist.");
                } else {
                    header = defaultHeader;
                }
            }
         try{
                settings = getFromTable(res, SETTINGS, UResourceBundle.ARRAY);
                info = getFromTable(res, INFO, UResourceBundle.TABLE);
            } catch (MissingResourceException e){
                // do nothing, left them null;
                settings = data;
            }
        }
        
        public String getName() {
            return res.getKey();
        }

        public DataMap getInfo() {
            return info == null ? null : new UTableResource(info);
        }

        public Iterator getSettingsIterator() {
            assert_is (settings.getType() == UResourceBundle.ARRAY);
            return new IteratorAdapter(settings){
                protected Object prepareNext(UResourceBundle nextRes) throws DataModuleFormatError {
                    return new UTableResource(nextRes);
                }
            };
        }

        public Iterator getDataIterator() {
            // unfortunately,
            assert_is (data.getType() == UResourceBundle.ARRAY 
                 || data.getType() == UResourceBundle.STRING);
            return new IteratorAdapter(data){
                protected Object prepareNext(UResourceBundle nextRes) throws DataModuleFormatError {
                    return new UArrayResource(header, nextRes);
                }
            };
        }
    }
        
    private static class UTableResource implements DataMap{
        private UResourceBundle res;

        UTableResource(UResourceBundle theRes){
            res = theRes;
        }
        public String getString(String key) {
            String t;
            try{
                t = res.getString(key);
            } catch (MissingResourceException e){
                t = null;
            }
            return t;
        }
         public Object getObject(String key) {
            
            return res.get(key);
        }
    }
    
    private static class UArrayResource implements DataMap{
        private Map theMap; 
        UArrayResource(UResourceBundle theHeader, UResourceBundle theData) throws DataModuleFormatError{
            assert_is (theHeader != null && theData != null);
            String[] header;
         
            header = getStringArrayHelper(theHeader);
            if (theData.getSize() != header.length) 
                throw new DataModuleFormatError("The count of Header and Data is mismatch.");
            theMap = new HashMap();
            for (int i = 0; i < header.length; i++) {
                if(theData.getType()==UResourceBundle.ARRAY){
                    theMap.put(header[i], theData.get(i));
                }else if(theData.getType()==UResourceBundle.STRING){
                    theMap.put(header[i], theData.getString());
                }else{
                    throw new DataModuleFormatError("Did not get the expected data!");                   
                }
            }
            
        }
        
        public String getString(String key) {
            Object o = theMap.get(key);
            UResourceBundle rb;
            if(o instanceof UResourceBundle) {
                // unpack ResourceBundle strings
                rb = (UResourceBundle)o;
                return rb.getString();
            }
            return (String)o;
        }
        public Object getObject(String key) {
            return theMap.get(key);
        }
    }
}
