// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
*   Copyright (C) 2011-2014, International Business Machines
*   Corporation and others.  All Rights Reserved.
*******************************************************************************
*   created on: 2011jul14
*   created by: Markus W. Scherer
*/

package com.ibm.icu.text;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Utilities for working with a MessagePattern.
 * Intended for use in tools when convenience is more important than
 * minimizing runtime and object creations.
 *
 * <p>This class only has static methods.
 * Each of the nested classes is immutable and thread-safe.
 *
 * <p>This class and its nested classes are not intended for public subclassing.
 * @stable ICU 49
 * @author Markus Scherer
 */
public final class MessagePatternUtil {

    // Private constructor preventing object instantiation
    private MessagePatternUtil() {
    }

    /**
     * Factory method, builds and returns a MessageNode from a MessageFormat pattern string.
     * @param patternString a MessageFormat pattern string
     * @return a MessageNode or a ComplexArgStyleNode
     * @throws IllegalArgumentException if the MessagePattern is empty
     *         or does not represent a MessageFormat pattern
     * @stable ICU 49
     */
    public static MessageNode buildMessageNode(String patternString) {
        return buildMessageNode(new MessagePattern(patternString));
    }

    /**
     * Factory method, builds and returns a MessageNode from a MessagePattern.
     * @param pattern a parsed MessageFormat pattern string
     * @return a MessageNode or a ComplexArgStyleNode
     * @throws IllegalArgumentException if the MessagePattern is empty
     *         or does not represent a MessageFormat pattern
     * @stable ICU 49
     */
    public static MessageNode buildMessageNode(MessagePattern pattern) {
        int limit = pattern.countParts() - 1;
        if (limit < 0) {
            throw new IllegalArgumentException("The MessagePattern is empty");
        } else if (pattern.getPartType(0) != MessagePattern.Part.Type.MSG_START) {
            throw new IllegalArgumentException(
            "The MessagePattern does not represent a MessageFormat pattern");
        }
        return buildMessageNode(pattern, 0, limit);
    }

    /**
     * Common base class for all elements in a tree of nodes
     * returned by {@link MessagePatternUtil#buildMessageNode(MessagePattern)}.
     * This class and all subclasses are immutable and thread-safe.
     * @stable ICU 49
     */
    public static class Node {
        private Node() {}
    }

    /**
     * A Node representing a parsed MessageFormat pattern string.
     * @stable ICU 49
     */
    public static class MessageNode extends Node {
        /**
         * @return the list of MessageContentsNode nodes that this message contains
         * @stable ICU 49
         */
        public List<MessageContentsNode> getContents() {
            return list;
        }
        /**
         * {@inheritDoc}
         * @stable ICU 49
         */
        @Override
        public String toString() {
            return list.toString();
        }

        private MessageNode() {
            super();
        }
        private void addContentsNode(MessageContentsNode node) {
            if (node instanceof TextNode && !list.isEmpty()) {
                // Coalesce adjacent text nodes.
                MessageContentsNode lastNode = list.get(list.size() - 1);
                if (lastNode instanceof TextNode) {
                    TextNode textNode = (TextNode)lastNode;
                    textNode.text = textNode.text + ((TextNode)node).text;
                    return;
                }
            }
            list.add(node);
        }
        private MessageNode freeze() {
            list = Collections.unmodifiableList(list);
            return this;
        }

        private volatile List<MessageContentsNode> list = new ArrayList<MessageContentsNode>();
    }

    /**
     * A piece of MessageNode contents.
     * Use getType() to determine the type and the actual Node subclass.
     * @stable ICU 49
     */
    public static class MessageContentsNode extends Node {
        /**
         * The type of a piece of MessageNode contents.
         * @stable ICU 49
         */
        public enum Type {
            /**
             * This is a TextNode containing literal text (downcast and call getText()).
             * @stable ICU 49
             */
            TEXT,
            /**
             * This is an ArgNode representing a message argument
             * (downcast and use specific methods).
             * @stable ICU 49
             */
            ARG,
            /**
             * This Node represents a place in a plural argument's variant where
             * the formatted (plural-offset) value is to be put.
             * @stable ICU 49
             */
            REPLACE_NUMBER
        }
        /**
         * Returns the type of this piece of MessageNode contents.
         * @stable ICU 49
         */
        public Type getType() {
            return type;
        }
        /**
         * {@inheritDoc}
         * @stable ICU 49
         */
        @Override
        public String toString() {
            // Note: There is no specific subclass for REPLACE_NUMBER
            // because it would not provide any additional API.
            // Therefore we have a little bit of REPLACE_NUMBER-specific code
            // here in the contents-node base class.
            return "{REPLACE_NUMBER}";
        }

        private MessageContentsNode(Type type) {
            super();
            this.type = type;
        }
        private static MessageContentsNode createReplaceNumberNode() {
            return new MessageContentsNode(Type.REPLACE_NUMBER);
        }

        private Type type;
    }

    /**
     * Literal text, a piece of MessageNode contents.
     * @stable ICU 49
     */
    public static class TextNode extends MessageContentsNode {
        /**
         * @return the literal text at this point in the message
         * @stable ICU 49
         */
        public String getText() {
            return text;
        }
        /**
         * {@inheritDoc}
         * @stable ICU 49
         */
        @Override
        public String toString() {
            return "«" + text + "»";
        }

        private TextNode(String text) {
            super(Type.TEXT);
            this.text = text;
        }

        private String text;
    }

    /**
     * A piece of MessageNode contents representing a message argument and its details.
     * @stable ICU 49
     */
    public static class ArgNode extends MessageContentsNode {
        /**
         * @return the argument type
         * @stable ICU 49
         */
        public MessagePattern.ArgType getArgType() {
            return argType;
        }
        /**
         * @return the argument name string (the decimal-digit string if the argument has a number)
         * @stable ICU 49
         */
        public String getName() {
            return name;
        }
        /**
         * @return the argument number, or -1 if none (for a named argument)
         * @stable ICU 49
         */
        public int getNumber() {
            return number;
        }
        /**
         * @return the argument type string, or null if none was specified
         * @stable ICU 49
         */
        public String getTypeName() {
            return typeName;
        }
        /**
         * @return the simple-argument style string,
         *         or null if no style is specified and for other argument types
         * @stable ICU 49
         */
        public String getSimpleStyle() {
            return style;
        }
        /**
         * @return the complex-argument-style object,
         *         or null if the argument type is NONE_ARG or SIMPLE_ARG
         * @stable ICU 49
         */
        public ComplexArgStyleNode getComplexStyle() {
            return complexStyle;
        }
        /**
         * {@inheritDoc}
         * @stable ICU 49
         */
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append('{').append(name);
            if (argType != MessagePattern.ArgType.NONE) {
                sb.append(',').append(typeName);
                if (argType == MessagePattern.ArgType.SIMPLE) {
                    if (style != null) {
                        sb.append(',').append(style);
                    }
                } else {
                    sb.append(',').append(complexStyle.toString());
                }
            }
            return sb.append('}').toString();
        }

        private ArgNode() {
            super(Type.ARG);
        }
        private static ArgNode createArgNode() {
            return new ArgNode();
        }

        private MessagePattern.ArgType argType;
        private String name;
        private int number = -1;
        private String typeName;
        private String style;
        private ComplexArgStyleNode complexStyle;
    }

    /**
     * A Node representing details of the argument style of a complex argument.
     * (Which is a choice/plural/select argument which selects among nested messages.)
     * @stable ICU 49
     */
    public static class ComplexArgStyleNode extends Node {
        /**
         * @return the argument type (same as getArgType() on the parent ArgNode)
         * @stable ICU 49
         */
        public MessagePattern.ArgType getArgType() {
            return argType;
        }
        /**
         * @return true if this is a plural style with an explicit offset
         * @stable ICU 49
         */
        public boolean hasExplicitOffset() {
            return explicitOffset;
        }
        /**
         * @return the plural offset, or 0 if this is not a plural style or
         *         the offset is explicitly or implicitly 0
         * @stable ICU 49
         */
        public double getOffset() {
            return offset;
        }
        /**
         * @return the list of variants: the nested messages with their selection criteria
         * @stable ICU 49
         */
        public List<VariantNode> getVariants() {
            return list;
        }
        /**
         * Separates the variants by type.
         * Intended for use with plural and select argument styles,
         * not useful for choice argument styles.
         *
         * <p>Both parameters are used only for output, and are first cleared.
         * @param numericVariants Variants with numeric-value selectors (if any) are added here.
         *        Can be null for a select argument style.
         * @param keywordVariants Variants with keyword selectors, except "other", are added here.
         *        For a plural argument, if this list is empty after the call, then
         *        all variants except "other" have explicit values
         *        and PluralRules need not be called.
         * @return the "other" variant (the first one if there are several),
         *         null if none (choice style)
         * @stable ICU 49
         */
        public VariantNode getVariantsByType(List<VariantNode> numericVariants,
                                             List<VariantNode> keywordVariants) {
            if (numericVariants != null) {
                numericVariants.clear();
            }
            keywordVariants.clear();
            VariantNode other = null;
            for (VariantNode variant : list) {
                if (variant.isSelectorNumeric()) {
                    numericVariants.add(variant);
                } else if ("other".equals(variant.getSelector())) {
                    if (other == null) {
                        // Return the first "other" variant. (MessagePattern allows duplicates.)
                        other = variant;
                    }
                } else {
                    keywordVariants.add(variant);
                }
            }
            return other;
        }
        /**
         * {@inheritDoc}
         * @stable ICU 49
         */
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append('(').append(argType.toString()).append(" style) ");
            if (hasExplicitOffset()) {
                sb.append("offset:").append(offset).append(' ');
            }
            return sb.append(list.toString()).toString();
        }

        private ComplexArgStyleNode(MessagePattern.ArgType argType) {
            super();
            this.argType = argType;
        }
        private void addVariant(VariantNode variant) {
            list.add(variant);
        }
        private ComplexArgStyleNode freeze() {
            list = Collections.unmodifiableList(list);
            return this;
        }

        private MessagePattern.ArgType argType;
        private double offset;
        private boolean explicitOffset;
        private volatile List<VariantNode> list = new ArrayList<VariantNode>();
    }

    /**
     * A Node representing a nested message (nested inside an argument)
     * with its selection criterion.
     * @stable ICU 49
     */
    public static class VariantNode extends Node {
        /**
         * Returns the selector string.
         * For example: A plural/select keyword ("few"), a plural explicit value ("=1"),
         * a choice comparison operator ("#").
         * @return the selector string
         * @stable ICU 49
         */
        public String getSelector() {
            return selector;
        }
        /**
         * @return true for choice variants and for plural explicit values
         * @stable ICU 49
         */
        public boolean isSelectorNumeric() {
            return numericValue != MessagePattern.NO_NUMERIC_VALUE;
        }
        /**
         * @return the selector's numeric value, or NO_NUMERIC_VALUE if !isSelectorNumeric()
         * @stable ICU 49
         */
        public double getSelectorValue() {
            return numericValue;
        }
        /**
         * @return the nested message
         * @stable ICU 49
         */
        public MessageNode getMessage() {
            return msgNode;
        }
        /**
         * {@inheritDoc}
         * @stable ICU 49
         */
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            if (isSelectorNumeric()) {
                sb.append(numericValue).append(" (").append(selector).append(") {");
            } else {
                sb.append(selector).append(" {");
            }
            return sb.append(msgNode.toString()).append('}').toString();
        }

        private VariantNode() {
            super();
        }

        private String selector;
        private double numericValue = MessagePattern.NO_NUMERIC_VALUE;
        private MessageNode msgNode;
    }

    private static MessageNode buildMessageNode(MessagePattern pattern, int start, int limit) {
        int prevPatternIndex = pattern.getPart(start).getLimit();
        MessageNode node = new MessageNode();
        for (int i = start + 1;; ++i) {
            MessagePattern.Part part = pattern.getPart(i);
            int patternIndex = part.getIndex();
            if (prevPatternIndex < patternIndex) {
                node.addContentsNode(
                        new TextNode(pattern.getPatternString().substring(prevPatternIndex,
                                     patternIndex)));
            }
            if (i == limit) {
                break;
            }
            MessagePattern.Part.Type partType = part.getType();
            if (partType == MessagePattern.Part.Type.ARG_START) {
                int argLimit = pattern.getLimitPartIndex(i);
                node.addContentsNode(buildArgNode(pattern, i, argLimit));
                i = argLimit;
                part = pattern.getPart(i);
            } else if (partType == MessagePattern.Part.Type.REPLACE_NUMBER) {
                node.addContentsNode(MessageContentsNode.createReplaceNumberNode());
                // else: ignore SKIP_SYNTAX and INSERT_CHAR parts.
            }
            prevPatternIndex = part.getLimit();
        }
        return node.freeze();
    }

    private static ArgNode buildArgNode(MessagePattern pattern, int start, int limit) {
        ArgNode node = ArgNode.createArgNode();
        MessagePattern.Part part = pattern.getPart(start);
        MessagePattern.ArgType argType = node.argType = part.getArgType();
        part = pattern.getPart(++start);  // ARG_NAME or ARG_NUMBER
        node.name = pattern.getSubstring(part);
        if (part.getType() == MessagePattern.Part.Type.ARG_NUMBER) {
            node.number = part.getValue();
        }
        ++start;
        switch(argType) {
        case SIMPLE:
            // ARG_TYPE
            node.typeName = pattern.getSubstring(pattern.getPart(start++));
            if (start < limit) {
                // ARG_STYLE
                node.style = pattern.getSubstring(pattern.getPart(start));
            }
            break;
        case CHOICE:
            node.typeName = "choice";
            node.complexStyle = buildChoiceStyleNode(pattern, start, limit);
            break;
        case PLURAL:
            node.typeName = "plural";
            node.complexStyle = buildPluralStyleNode(pattern, start, limit, argType);
            break;
        case SELECT:
            node.typeName = "select";
            node.complexStyle = buildSelectStyleNode(pattern, start, limit);
            break;
        case SELECTORDINAL:
            node.typeName = "selectordinal";
            node.complexStyle = buildPluralStyleNode(pattern, start, limit, argType);
            break;
        default:
            // NONE type, nothing else to do
            break;
        }
        return node;
    }

    private static ComplexArgStyleNode buildChoiceStyleNode(MessagePattern pattern,
                                                            int start, int limit) {
        ComplexArgStyleNode node = new ComplexArgStyleNode(MessagePattern.ArgType.CHOICE);
        while (start < limit) {
            int valueIndex = start;
            MessagePattern.Part part = pattern.getPart(start);
            double value = pattern.getNumericValue(part);
            start += 2;
            int msgLimit = pattern.getLimitPartIndex(start);
            VariantNode variant = new VariantNode();
            variant.selector = pattern.getSubstring(pattern.getPart(valueIndex + 1));
            variant.numericValue = value;
            variant.msgNode = buildMessageNode(pattern, start, msgLimit);
            node.addVariant(variant);
            start = msgLimit + 1;
        }
        return node.freeze();
    }

    private static ComplexArgStyleNode buildPluralStyleNode(MessagePattern pattern,
                                                            int start, int limit,
                                                            MessagePattern.ArgType argType) {
        ComplexArgStyleNode node = new ComplexArgStyleNode(argType);
        MessagePattern.Part offset = pattern.getPart(start);
        if (offset.getType().hasNumericValue()) {
            node.explicitOffset = true;
            node.offset = pattern.getNumericValue(offset);
            ++start;
        }
        while (start < limit) {
            MessagePattern.Part selector = pattern.getPart(start++);
            double value = MessagePattern.NO_NUMERIC_VALUE;
            MessagePattern.Part part = pattern.getPart(start);
            if (part.getType().hasNumericValue()) {
                value = pattern.getNumericValue(part);
                ++start;
            }
            int msgLimit = pattern.getLimitPartIndex(start);
            VariantNode variant = new VariantNode();
            variant.selector = pattern.getSubstring(selector);
            variant.numericValue = value;
            variant.msgNode = buildMessageNode(pattern, start, msgLimit);
            node.addVariant(variant);
            start = msgLimit + 1;
        }
        return node.freeze();
    }

    private static ComplexArgStyleNode buildSelectStyleNode(MessagePattern pattern,
                                                            int start, int limit) {
        ComplexArgStyleNode node = new ComplexArgStyleNode(MessagePattern.ArgType.SELECT);
        while (start < limit) {
            MessagePattern.Part selector = pattern.getPart(start++);
            int msgLimit = pattern.getLimitPartIndex(start);
            VariantNode variant = new VariantNode();
            variant.selector = pattern.getSubstring(selector);
            variant.msgNode = buildMessageNode(pattern, start, msgLimit);
            node.addVariant(variant);
            start = msgLimit + 1;
        }
        return node.freeze();
    }
}
