/*
 * Decompiled with CFR 0.152.
 */
package org.yaml.snakeyaml.constructor;

import java.math.BigInteger;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.yaml.snakeyaml.constructor.AbstractConstruct;
import org.yaml.snakeyaml.constructor.BaseConstructor;
import org.yaml.snakeyaml.constructor.Construct;
import org.yaml.snakeyaml.constructor.ConstructorException;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;
import org.yaml.snakeyaml.nodes.Tag;

/*
 * This class specifies class file version 49.0 but uses Java 6 signatures.  Assumed Java 6.
 */
public class SafeConstructor
extends BaseConstructor {
    public static final ConstructUndefined undefinedConstructor = new ConstructUndefined();
    private static final Map<String, Boolean> BOOL_VALUES = new HashMap<String, Boolean>();
    private static final Pattern TIMESTAMP_REGEXP;
    private static final Pattern YMD_REGEXP;

    public SafeConstructor() {
        this.yamlConstructors.put(Tag.NULL, new ConstructYamlNull());
        this.yamlConstructors.put(Tag.BOOL, new ConstructYamlBool());
        this.yamlConstructors.put(Tag.INT, new ConstructYamlInt());
        this.yamlConstructors.put(Tag.FLOAT, new ConstructYamlFloat());
        this.yamlConstructors.put(Tag.BINARY, new ConstructYamlBinary());
        this.yamlConstructors.put(Tag.TIMESTAMP, new ConstructYamlTimestamp());
        this.yamlConstructors.put(Tag.OMAP, new ConstructYamlOmap());
        this.yamlConstructors.put(Tag.PAIRS, new ConstructYamlPairs());
        this.yamlConstructors.put(Tag.SET, new ConstructYamlSet());
        this.yamlConstructors.put(Tag.STR, new ConstructYamlStr());
        this.yamlConstructors.put(Tag.SEQ, new ConstructYamlSeq());
        this.yamlConstructors.put(Tag.MAP, new ConstructYamlMap());
        this.yamlConstructors.put(null, undefinedConstructor);
        this.yamlClassConstructors.put(NodeId.scalar, undefinedConstructor);
        this.yamlClassConstructors.put(NodeId.sequence, undefinedConstructor);
        this.yamlClassConstructors.put(NodeId.mapping, undefinedConstructor);
    }

    protected void flattenMapping(MappingNode node) {
        if (node.isMerged()) {
            node.setValue(this.mergeNode(node, true, new HashMap<Object, Integer>(), new ArrayList<NodeTuple>()));
        }
    }

    private List<NodeTuple> mergeNode(MappingNode node, boolean isPreffered, Map<Object, Integer> key2index, List<NodeTuple> values) {
        List<NodeTuple> nodeValue = node.getValue();
        Collections.reverse(nodeValue);
        Iterator<NodeTuple> iter = nodeValue.iterator();
        block4: while (iter.hasNext()) {
            NodeTuple nodeTuple = iter.next();
            Node keyNode = nodeTuple.getKeyNode();
            Node valueNode = nodeTuple.getValueNode();
            if (keyNode.getTag().equals(Tag.MERGE)) {
                iter.remove();
                switch (valueNode.getNodeId()) {
                    case mapping: {
                        MappingNode mn = (MappingNode)valueNode;
                        this.mergeNode(mn, false, key2index, values);
                        break;
                    }
                    case sequence: {
                        SequenceNode sn = (SequenceNode)valueNode;
                        List<Node> vals = sn.getValue();
                        for (Node subnode : vals) {
                            if (!(subnode instanceof MappingNode)) {
                                throw new ConstructorException("while constructing a mapping", node.getStartMark(), "expected a mapping for merging, but found " + (Object)((Object)subnode.getNodeId()), subnode.getStartMark());
                            }
                            MappingNode mnode = (MappingNode)subnode;
                            this.mergeNode(mnode, false, key2index, values);
                        }
                        continue block4;
                    }
                    default: {
                        throw new ConstructorException("while constructing a mapping", node.getStartMark(), "expected a mapping or list of mappings for merging, but found " + (Object)((Object)valueNode.getNodeId()), valueNode.getStartMark());
                    }
                }
                continue;
            }
            Object key = this.constructObject(keyNode);
            if (!key2index.containsKey(key)) {
                values.add(nodeTuple);
                key2index.put(key, values.size() - 1);
                continue;
            }
            if (!isPreffered) continue;
            values.set(key2index.get(key), nodeTuple);
        }
        return values;
    }

    @Override
    protected void constructMapping2ndStep(MappingNode node, Map<Object, Object> mapping) {
        this.flattenMapping(node);
        super.constructMapping2ndStep(node, mapping);
    }

    @Override
    protected void constructSet2ndStep(MappingNode node, Set<Object> set) {
        this.flattenMapping(node);
        super.constructSet2ndStep(node, set);
    }

    private Number createNumber(int sign, String number, int radix) {
        Number result;
        if (sign < 0) {
            number = "-" + number;
        }
        try {
            result = Integer.valueOf(number, radix);
        }
        catch (NumberFormatException e) {
            try {
                result = Long.valueOf(number, radix);
            }
            catch (NumberFormatException e1) {
                result = new BigInteger(number, radix);
            }
        }
        return result;
    }

    static {
        BOOL_VALUES.put("yes", Boolean.TRUE);
        BOOL_VALUES.put("no", Boolean.FALSE);
        BOOL_VALUES.put("true", Boolean.TRUE);
        BOOL_VALUES.put("false", Boolean.FALSE);
        BOOL_VALUES.put("on", Boolean.TRUE);
        BOOL_VALUES.put("off", Boolean.FALSE);
        TIMESTAMP_REGEXP = Pattern.compile("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:(?:[Tt]|[ \t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \t]*(?:Z|([-+][0-9][0-9]?)(?::([0-9][0-9])?)?))?)?$");
        YMD_REGEXP = Pattern.compile("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)$");
    }

    public static final class ConstructUndefined
    extends AbstractConstruct {
        public Object construct(Node node) {
            throw new ConstructorException(null, null, "could not determine a constructor for the tag " + node.getTag(), node.getStartMark());
        }
    }

    public class ConstructYamlMap
    implements Construct {
        public Object construct(Node node) {
            if (node.isTwoStepsConstruction()) {
                return SafeConstructor.this.createDefaultMap();
            }
            return SafeConstructor.this.constructMapping((MappingNode)node);
        }

        public void construct2ndStep(Node node, Object object) {
            if (!node.isTwoStepsConstruction()) {
                throw new YAMLException("Unexpected recursive mapping structure. Node: " + node);
            }
            SafeConstructor.this.constructMapping2ndStep((MappingNode)node, (Map)object);
        }
    }

    public class ConstructYamlSeq
    implements Construct {
        public Object construct(Node node) {
            SequenceNode seqNode = (SequenceNode)node;
            if (node.isTwoStepsConstruction()) {
                return SafeConstructor.this.createDefaultList(seqNode.getValue().size());
            }
            return SafeConstructor.this.constructSequence(seqNode);
        }

        public void construct2ndStep(Node node, Object data) {
            if (!node.isTwoStepsConstruction()) {
                throw new YAMLException("Unexpected recursive sequence structure. Node: " + node);
            }
            SafeConstructor.this.constructSequenceStep2((SequenceNode)node, (List)data);
        }
    }

    public class ConstructYamlStr
    extends AbstractConstruct {
        public Object construct(Node node) {
            return SafeConstructor.this.constructScalar((ScalarNode)node);
        }
    }

    public class ConstructYamlSet
    implements Construct {
        public Object construct(Node node) {
            if (node.isTwoStepsConstruction()) {
                return SafeConstructor.this.createDefaultSet();
            }
            return SafeConstructor.this.constructSet((MappingNode)node);
        }

        public void construct2ndStep(Node node, Object object) {
            if (!node.isTwoStepsConstruction()) {
                throw new YAMLException("Unexpected recursive set structure. Node: " + node);
            }
            SafeConstructor.this.constructSet2ndStep((MappingNode)node, (Set)object);
        }
    }

    public class ConstructYamlPairs
    extends AbstractConstruct {
        public Object construct(Node node) {
            if (!(node instanceof SequenceNode)) {
                throw new ConstructorException("while constructing pairs", node.getStartMark(), "expected a sequence, but found " + (Object)((Object)node.getNodeId()), node.getStartMark());
            }
            SequenceNode snode = (SequenceNode)node;
            ArrayList<Object[]> pairs = new ArrayList<Object[]>(snode.getValue().size());
            for (Node subnode : snode.getValue()) {
                if (!(subnode instanceof MappingNode)) {
                    throw new ConstructorException("while constructingpairs", node.getStartMark(), "expected a mapping of length 1, but found " + (Object)((Object)subnode.getNodeId()), subnode.getStartMark());
                }
                MappingNode mnode = (MappingNode)subnode;
                if (mnode.getValue().size() != 1) {
                    throw new ConstructorException("while constructing pairs", node.getStartMark(), "expected a single mapping item, but found " + mnode.getValue().size() + " items", mnode.getStartMark());
                }
                Node keyNode = mnode.getValue().get(0).getKeyNode();
                Node valueNode = mnode.getValue().get(0).getValueNode();
                Object key = SafeConstructor.this.constructObject(keyNode);
                Object value = SafeConstructor.this.constructObject(valueNode);
                pairs.add(new Object[]{key, value});
            }
            return pairs;
        }
    }

    public class ConstructYamlOmap
    extends AbstractConstruct {
        public Object construct(Node node) {
            LinkedHashMap<Object, Object> omap = new LinkedHashMap<Object, Object>();
            if (!(node instanceof SequenceNode)) {
                throw new ConstructorException("while constructing an ordered map", node.getStartMark(), "expected a sequence, but found " + (Object)((Object)node.getNodeId()), node.getStartMark());
            }
            SequenceNode snode = (SequenceNode)node;
            for (Node subnode : snode.getValue()) {
                if (!(subnode instanceof MappingNode)) {
                    throw new ConstructorException("while constructing an ordered map", node.getStartMark(), "expected a mapping of length 1, but found " + (Object)((Object)subnode.getNodeId()), subnode.getStartMark());
                }
                MappingNode mnode = (MappingNode)subnode;
                if (mnode.getValue().size() != 1) {
                    throw new ConstructorException("while constructing an ordered map", node.getStartMark(), "expected a single mapping item, but found " + mnode.getValue().size() + " items", mnode.getStartMark());
                }
                Node keyNode = mnode.getValue().get(0).getKeyNode();
                Node valueNode = mnode.getValue().get(0).getValueNode();
                Object key = SafeConstructor.this.constructObject(keyNode);
                Object value = SafeConstructor.this.constructObject(valueNode);
                omap.put(key, value);
            }
            return omap;
        }
    }

    public static class ConstructYamlTimestamp
    extends AbstractConstruct {
        private Calendar calendar;

        public Calendar getCalendar() {
            return this.calendar;
        }

        public Object construct(Node node) {
            TimeZone timeZone;
            ScalarNode scalar = (ScalarNode)node;
            String nodeValue = scalar.getValue();
            Matcher match = YMD_REGEXP.matcher(nodeValue);
            if (match.matches()) {
                String year_s = match.group(1);
                String month_s = match.group(2);
                String day_s = match.group(3);
                this.calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
                this.calendar.clear();
                this.calendar.set(1, Integer.parseInt(year_s));
                this.calendar.set(2, Integer.parseInt(month_s) - 1);
                this.calendar.set(5, Integer.parseInt(day_s));
                return this.calendar.getTime();
            }
            match = TIMESTAMP_REGEXP.matcher(nodeValue);
            if (!match.matches()) {
                throw new YAMLException("Unexpected timestamp: " + nodeValue);
            }
            String year_s = match.group(1);
            String month_s = match.group(2);
            String day_s = match.group(3);
            String hour_s = match.group(4);
            String min_s = match.group(5);
            String seconds = match.group(6);
            String millis = match.group(7);
            if (millis != null) {
                seconds = seconds + "." + millis;
            }
            double fractions = Double.parseDouble(seconds);
            int sec_s = (int)Math.round(Math.floor(fractions));
            int usec = (int)Math.round((fractions - (double)sec_s) * 1000.0);
            String timezoneh_s = match.group(8);
            String timezonem_s = match.group(9);
            if (timezoneh_s != null) {
                String time = timezonem_s != null ? ":" + timezonem_s : "00";
                timeZone = TimeZone.getTimeZone("GMT" + timezoneh_s + time);
            } else {
                timeZone = TimeZone.getTimeZone("UTC");
            }
            this.calendar = Calendar.getInstance(timeZone);
            this.calendar.set(1, Integer.parseInt(year_s));
            this.calendar.set(2, Integer.parseInt(month_s) - 1);
            this.calendar.set(5, Integer.parseInt(day_s));
            this.calendar.set(11, Integer.parseInt(hour_s));
            this.calendar.set(12, Integer.parseInt(min_s));
            this.calendar.set(13, sec_s);
            this.calendar.set(14, usec);
            return this.calendar.getTime();
        }
    }

    public class ConstructYamlNumber
    extends AbstractConstruct {
        private final NumberFormat nf = NumberFormat.getInstance();

        public Object construct(Node node) {
            ScalarNode scalar = (ScalarNode)node;
            try {
                return this.nf.parse(scalar.getValue());
            }
            catch (ParseException e) {
                String lowerCaseValue = scalar.getValue().toLowerCase();
                if (lowerCaseValue.contains("inf") || lowerCaseValue.contains("nan")) {
                    return (Number)((Construct)SafeConstructor.this.yamlConstructors.get(Tag.FLOAT)).construct(node);
                }
                throw new IllegalArgumentException("Unable to parse as Number: " + scalar.getValue());
            }
        }
    }

    public class ConstructYamlBinary
    extends AbstractConstruct {
        public Object construct(Node node) {
            byte[] decoded = Base64Coder.decode(SafeConstructor.this.constructScalar((ScalarNode)node).toString().toCharArray());
            return decoded;
        }
    }

    public class ConstructYamlFloat
    extends AbstractConstruct {
        public Object construct(Node node) {
            String value = SafeConstructor.this.constructScalar((ScalarNode)node).toString().replaceAll("_", "");
            int sign = 1;
            char first = value.charAt(0);
            if (first == '-') {
                sign = -1;
                value = value.substring(1);
            } else if (first == '+') {
                value = value.substring(1);
            }
            String valLower = value.toLowerCase();
            if (".inf".equals(valLower)) {
                return new Double(sign == -1 ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY);
            }
            if (".nan".equals(valLower)) {
                return new Double(Double.NaN);
            }
            if (value.indexOf(58) != -1) {
                String[] digits = value.split(":");
                int bes = 1;
                double val = 0.0;
                int j = digits.length;
                for (int i = 0; i < j; ++i) {
                    val += Double.parseDouble(digits[j - i - 1]) * (double)bes;
                    bes *= 60;
                }
                return new Double((double)sign * val);
            }
            Double d = Double.valueOf(value);
            return new Double(d * (double)sign);
        }
    }

    public class ConstructYamlInt
    extends AbstractConstruct {
        public Object construct(Node node) {
            String value = SafeConstructor.this.constructScalar((ScalarNode)node).toString().replaceAll("_", "");
            int sign = 1;
            char first = value.charAt(0);
            if (first == '-') {
                sign = -1;
                value = value.substring(1);
            } else if (first == '+') {
                value = value.substring(1);
            }
            int base = 10;
            if ("0".equals(value)) {
                return 0;
            }
            if (value.startsWith("0b")) {
                value = value.substring(2);
                base = 2;
            } else if (value.startsWith("0x")) {
                value = value.substring(2);
                base = 16;
            } else if (value.startsWith("0")) {
                value = value.substring(1);
                base = 8;
            } else {
                if (value.indexOf(58) != -1) {
                    String[] digits = value.split(":");
                    int bes = 1;
                    int val = 0;
                    int j = digits.length;
                    for (int i = 0; i < j; ++i) {
                        val = (int)((long)val + Long.parseLong(digits[j - i - 1]) * (long)bes);
                        bes *= 60;
                    }
                    return SafeConstructor.this.createNumber(sign, String.valueOf(val), 10);
                }
                return SafeConstructor.this.createNumber(sign, value, 10);
            }
            return SafeConstructor.this.createNumber(sign, value, base);
        }
    }

    public class ConstructYamlBool
    extends AbstractConstruct {
        public Object construct(Node node) {
            String val = (String)SafeConstructor.this.constructScalar((ScalarNode)node);
            return BOOL_VALUES.get(val.toLowerCase());
        }
    }

    public class ConstructYamlNull
    extends AbstractConstruct {
        public Object construct(Node node) {
            SafeConstructor.this.constructScalar((ScalarNode)node);
            return null;
        }
    }
}
