/*
*******************************************************************************
*   Copyright (C) 2010-2011, International Business Machines
*   Corporation and others.  All Rights Reserved.
*******************************************************************************
*   created on: 2010aug21
*   created by: Markus W. Scherer
*/

package com.ibm.icu.samples.text.messagepattern;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.ibm.icu.text.MessagePattern;
import com.ibm.icu.text.MessagePattern.ArgType;
import com.ibm.icu.text.MessagePattern.Part;
import com.ibm.icu.util.Freezable;

/**
 * Mini message formatter for a small subset of the ICU MessageFormat syntax.
 * Supports only string substitution and select formatting.
 * @author Markus Scherer
 * @since 2010-aug-21
 */
public final class MiniMessageFormatter implements Freezable<MiniMessageFormatter> {
    public MiniMessageFormatter() {
        this.msg=new MessagePattern();
    }

    public MiniMessageFormatter(MessagePattern msg) {
        this.msg=(MessagePattern)msg.clone();
    }

    public MiniMessageFormatter(String msg) {
        this.msg=new MessagePattern(msg);
    }

    public MiniMessageFormatter applyPattern(String msg) {
        this.msg.parse(msg);
        return this;
    }

    public String getPatternString() {
        return msg.getPatternString();
    }

    public boolean hasNamedArguments() {
        return msg.hasNamedArguments();
    }

    public boolean hasNumberedArguments() {
        return msg.hasNumberedArguments();
    }

    /**
     * Formats the parsed message with positional arguments.
     * Supports only string substitution (e.g., {3}) and select format.
     * @param dest gets the formatted message appended
     * @param args positional arguments
     * @return dest
     */
    public Appendable format(Appendable dest, Object... args) {
        if(msg.hasNamedArguments()) {
            throw new IllegalArgumentException(
                "Formatting message with named arguments using positional argument values.");
        }
        format(0, dest, args, null);
        return dest;
    }

    public static final String format(String msg, Object... args) {
        return new MiniMessageFormatter(msg).format(new StringBuilder(2*msg.length()), args).toString();
    }

    public Appendable format(Appendable dest, Map<String, Object> argsMap) {
        if(msg.hasNumberedArguments()) {
            throw new IllegalArgumentException(
                "Formatting message with numbered arguments using named argument values.");
        }
        format(0, dest, null, argsMap);
        return dest;
    }

    public static final String format(String msg, Map<String, Object> argsMap) {
        return new MiniMessageFormatter(msg).format(new StringBuilder(2*msg.length()), argsMap).toString();
    }

    private int format(int msgStart, Appendable dest, Object[] args, Map<String, Object> argsMap) {
        try {
            String msgString=msg.getPatternString();
            int prevIndex=msg.getPart(msgStart).getLimit();
            for(int i=msgStart+1;; ++i) {
                Part part=msg.getPart(i);
                Part.Type type=part.getType();
                int index=part.getIndex();
                dest.append(msgString, prevIndex, index);
                if(type==Part.Type.MSG_LIMIT) {
                    return i;
                }
                if(type==Part.Type.SKIP_SYNTAX || type==Part.Type.INSERT_CHAR) {
                    prevIndex=part.getLimit();
                    continue;
                }
                assert type==Part.Type.ARG_START : "Unexpected Part "+part+" in parsed message.";
                int argLimit=msg.getLimitPartIndex(i);
                ArgType argType=part.getArgType();
                part=msg.getPart(++i);
                Object arg;
                if(args!=null) {
                    try {
                        arg=args[part.getValue()];  // args[ARG_NUMBER]
                    } catch(IndexOutOfBoundsException e) {
                        throw new IndexOutOfBoundsException(
                            "No argument at index "+part.getValue());
                    }
                } else {
                    arg=argsMap.get(msg.getSubstring(part));  // args[ARG_NAME]
                    if(arg==null) {
                        throw new IndexOutOfBoundsException(
                            "No argument for name "+msg.getSubstring(part));
                    }
                }
                String argValue=arg.toString();
                ++i;
                if(argType==ArgType.NONE) {
                    dest.append(argValue);
                } else if(argType==ArgType.SELECT) {
                    // Similar to SelectFormat.findSubMessage().
                    int subMsgStart=0;
                    for(;; ++i) {  // (ARG_SELECTOR, message) pairs until ARG_LIMIT
                        part=msg.getPart(i++);
                        if(part.getType()==Part.Type.ARG_LIMIT) {
                            assert subMsgStart!=0;  // The parser made sure this is the case.
                            break;
                        // else: part is an ARG_SELECTOR followed by a message
                        } else if(msg.partSubstringMatches(part, argValue)) {
                            // keyword matches
                            subMsgStart=i;
                            break;
                        } else if(subMsgStart==0 && msg.partSubstringMatches(part, "other")) {
                            subMsgStart=i;
                        }
                        i=msg.getLimitPartIndex(i);
                    }
                    format(subMsgStart, dest, args, argsMap);
                } else {
                    throw new UnsupportedOperationException("Unsupported argument type "+argType);
                }
                prevIndex=msg.getPart(argLimit).getLimit();
                i=argLimit;
            }
        } catch(IOException e) {  // Appendable throws IOException
            throw new RuntimeException(e);  // We do not want a throws clause.
        }
    }

    /**
     * Presents an array of (String, Object) pairs as a Map.
     * Only for temporary use for formatting with named arguments.
     */
    public static Map<String, Object> mapFromNameValuePairs(Object[] args) {
        HashMap<String, Object> argsMap = new HashMap<String, Object>();
        for(int i=0; i<args.length; i+=2) {
            argsMap.put((String)args[i], args[i+1]);
        }
        return argsMap;
    }

    public MiniMessageFormatter cloneAsThawed() {
        // TODO Auto-generated method stub
        return null;
    }

    public MiniMessageFormatter freeze() {
        msg.freeze();
        return this;
    }

    public boolean isFrozen() {
        return msg.isFrozen();
    }

    private final MessagePattern msg;
}
