// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
 *******************************************************************************
 * Copyright (C) 2007, International Business Machines Corporation and         *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.dev.test.util;

import com.ibm.icu.impl.Utility;

/**
 * @author srl
 * 
 * analog of FieldsSet in C++
 */
public class FieldsSet {
    public static final int NO_ENUM = -1;

    protected FieldsSet(int whichEnum, int fieldsCount) {
        if (fieldsCount <= 0 && whichEnum != NO_ENUM) {
            fieldsCount = DebugUtilities.enumCount(whichEnum);
        }
        fEnum = whichEnum;
        fFieldsCount = fieldsCount;
        if(fieldsCount<0) {
            throw new InternalError("Preposterous field count " + fieldsCount);
        }
        fValues = new int[fFieldsCount];
        fIsSet = new boolean[fFieldsCount];
        clear();
    }

    protected int fEnum = NO_ENUM;

    protected int fFieldsCount = 0;

    protected int fValues[] = null;

    protected boolean fIsSet[] = null;

    public void clear() {
        for (int i = 0; i < fFieldsCount; i++) {
            clear(i);
        }
    }

    public void clear(int field) {
        fValues[field] = -1;
        fIsSet[field] = false;
    }

    public void set(int field, int amount) {
        fValues[field] = amount;
        fIsSet[field] = true;
    }

    public boolean isSet(int field) {
        return fIsSet[field];
    }

    public int get(int field) {
        if (fIsSet[field]) {
            return fValues[field];
        } else {
            return -1;
        }
    }

    public boolean isSameType(FieldsSet other) {
        return ((other.fEnum == fEnum) && (other.fFieldsCount == fFieldsCount));
    }

    public int fieldCount() {
        return fFieldsCount;
    }

    /**
     * @param other  "expected" set to match against
     * @return a formatted string listing which fields are set in this, with the
     *         comparison made agaainst those fields in other, or, 'null' if there is no difference.
     */
    public String diffFrom(FieldsSet other) {
        StringBuffer str = new StringBuffer();
        if(!isSameType(other)) {
            throw new IllegalArgumentException("U_ILLEGAL_ARGUMENT_ERROR: FieldsSet of a different type!");
        }
        for (int i=0; i<fieldCount(); i++) {
            if (isSet(i)) {
                int myVal = get(i);
                int theirVal = other.get(i);
                
                if(fEnum != NO_ENUM) {
                    String fieldName = DebugUtilities.enumString(fEnum, i);
                    
                    String aval = Integer.toString(myVal);
                    String bval = Integer.toString(theirVal);

                    str.append(fieldName +"="+aval+" not "+bval+", ");
                } else {
                    str.append(Integer.toString(i) + "=" + myVal+" not " + theirVal+", ");
                }
            }
        }
        if(str.length()==0) {
            return null;
        }
        return str.toString();
    }

    /**
     * @param str string to parse
     * @param status formatted string for status
     */
    public int parseFrom(String str) {
        return parseFrom(str, null);
    }

    public int parseFrom(String str, FieldsSet inheritFrom) {
        int goodFields = 0;
        
        String[] fields = Utility.split(str, ',');
        for(int i=0;i<fields.length;i++) {
            String fieldStr = fields[i];
            String kv[] = Utility.split(fieldStr, '=');
            if(kv.length < 1 || kv.length > 2) {
                throw new InternalError("split around '=' failed: " + fieldStr);
            }
            String key = kv[0];
            String value = "";
            if(kv.length>1) {
                value = kv[1];
            }
            
            int field = handleParseName(inheritFrom, key, value);
            if(field != -1) {
                handleParseValue(inheritFrom, field, value);
                goodFields++;
            }
        }

        return goodFields;
    }

    /**
     * Callback interface for subclass. This function is called when parsing a
     * field name, such as "MONTH" in "MONTH=4". Base implementation is to
     * lookup the enum value using udbg_* utilities, or else as an integer if
     * enum is not available.
     * 
     * If there is a special directive, the implementer can catch it here and
     * return -1 after special processing completes.
     * 
     * @param inheritFrom  the set inheriting from - may be null.
     * @param name  the field name (key side)
     * @param substr  the string in question (value side)
     * @param status  error status - set to error for failure.
     * @return field number, or negative if field should be skipped.
     */
    protected int handleParseName(FieldsSet inheritFrom, String name,
            String substr) {
        int field = -1;
        if(fEnum != NO_ENUM) {
            field = DebugUtilities.enumByString(fEnum, name);
        }
        if(field < 0) {
            field = Integer.parseInt(name);
        }
        return field;
    }

    /**
     * Callback interface for subclass. Base implementation is to call
     * parseValueDefault(...)
     * 
     * @param inheritFrom  the set inheriting from - may be null.
     * @param field   which field is being parsed
     * @param substr  the string in question (value side)
     * @param status  error status - set to error for failure.
     * @see parseValueDefault
     */
    protected void handleParseValue(FieldsSet inheritFrom, int field,
            String substr) {
        parseValueDefault(inheritFrom, field, substr);
    }

    /**
     * the default implementation for handleParseValue. Base implementation is
     * to parse a decimal integer value, or inherit from inheritFrom if the
     * string is 0-length. Implementations of this function should call
     * set(field,...) on successful parse.
     * 
     * @see handleParseValue
     */
    protected void parseValueDefault(FieldsSet inheritFrom, int field,
            String substr) {
        if(substr.length()==0) {
            if(inheritFrom == null) {
                throw new InternalError("Trying to inherit from field " + field + " but inheritFrom is null");
            }
            if(!inheritFrom.isSet(field)) {
                throw new InternalError("Trying to inherit from field " + field + " but inheritFrom["+field+"] is  not set");
            }
            set(field,inheritFrom.get(field));
        } else {
            int value = Integer.parseInt(substr);
            set(field, value);
        }
    }

    /**
     * convenience implementation for handleParseValue attempt to load a value
     * from an enum value using udbg_enumByString() if fails, will call
     * parseValueDefault()
     * 
     * @see handleParseValue
     */
    protected void parseValueEnum(int type, FieldsSet inheritFrom, int field,
            String substr) {
        int value = DebugUtilities.enumByString(type, substr);
        if(value>=0) {
            set(field,value);
            return;
        }
        parseValueDefault(inheritFrom, field, substr);
    }
    
    public String fieldName(int field) {
        return (fEnum!=NO_ENUM)?DebugUtilities.enumString(fEnum, field):Integer.toString(field);
    }
    
    public String toString() {
        String str = getClass().getName()+" ["+fFieldsCount+","
        +(fEnum!=NO_ENUM?DebugUtilities.typeString(fEnum):Integer.toString(fEnum))+"]: ";
        for(int i=0;i<fFieldsCount;i++) {
            if(isSet(i)) {
                str = str + fieldName(i)+"="+get(i)+",";
            }
        }
        return str; 
    }
}
