/*
 * Copyright (C) 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.i18n.addressinput;

import java.util.Collections;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Wraps a Map of address property data to provide the AddressVerificationData API.
 */
public class AddressVerificationData implements DataSource{

    private final Map<String, String> propertiesMap;

    private static final Pattern KV_PAT = Pattern.compile("\"([^\"]+)\":\"([^\"]*)\"");

    private static final Pattern SEP_PAT = Pattern.compile("\",\"");

    /**
     * Constructs from a map of address property data.  This keeps a reference to the map.  This
     * does not mutate the map. The map should not be mutated subsequent to this call.
     */
    public AddressVerificationData(Map<String, String> propertiesMap) {
        this.propertiesMap = propertiesMap;
    }

    public AddressVerificationNodeData get(String key) {
        String json = propertiesMap.get(key);
        if (json != null && isValidKey(key)) {
            return createNodeData(json);
        }
        return null;
    }

    /**
     * Returns a set of the keys for which verification data is provided.  The returned set is
     * immutable.
     */
    public Set<String> keys() {
        Set<String> result = new HashSet<String>();
        for (String key : propertiesMap.keySet()) {
            if (isValidKey(key)) {
                result.add(key);
            }
        }
        return Collections.unmodifiableSet(result);
    }

    /**
     * We can be initialized with the full set of address information, but validation only uses info
     * prefixed with "data" (in particular, no info prefixed with "examples").
     */
    private boolean isValidKey(String key) {
        return key.startsWith("data");
    }

    /**
     * Returns the contents of the JSON-format string as a map.
     */
    protected AddressVerificationNodeData createNodeData(String json) {
        // Remove leading and trailing { and }.
        json = json.substring(1, json.length() - 1);
        Map<AddressDataKey, String> map =
                new EnumMap<AddressDataKey, String>(AddressDataKey.class);

        // our objects are very simple so we parse manually
        // - no double quotes within strings
        // - no extra spaces
        // can't use split "," since some data has commas in it.
        Matcher sm = SEP_PAT.matcher(json);
        int pos = 0;
        while (pos < json.length()) {
            String pair;
            if (sm.find()) {
                pair = json.substring(pos, sm.start() + 1);
                pos = sm.start() + 2;
            } else {
                pair = json.substring(pos);
                pos = json.length();
            }

            Matcher m = KV_PAT.matcher(pair);
            if (m.matches()) {
                String value = m.group(2);

                // Remove escaped backslashes.
                // Java regex doesn't handle a replacement String consisting of
                // a single backslash, and treats a replacement String consisting of
                // two backslashes as two backslashes instead of one.  So there's
                // no way to use regex to replace a match with a single backslash,
                // apparently.
                if (value.length() > 0) {
                    char[] linechars = m.group(2).toCharArray();
                    int w = 1;
                    for (int r = w; r < linechars.length; ++r) {
                        char c = linechars[r];
                        if (c == '\\' && linechars[w - 1] == '\\') {
                            // don't increment w;
                            continue;
                        }
                        linechars[w++] = c;
                    }
                    value = new String(linechars, 0, w);
                }

                AddressDataKey df = AddressDataKey.get(m.group(1));
                if (df == null) {
                    // This is a runtime data sanity check.  The data should be
                    // checked when the data is built.  There should be no key
                    // that does not match an AddressDataField.
                    throw new RuntimeException("unknown field for key '" + m.group(1) + "'");
                }
                map.put(df, value);
            } else {
                // This is a runtime data sanity check.  The data should be
                // checked when the data is built.  The JSON data string should
                // be parsable into string pairs using SEP_PAT.
                throw new RuntimeException("could not match '" + pair + "' in '" + json + "'");
            }
        }

        return new AddressVerificationNodeData(map);
    }

    public AddressVerificationNodeData getDefaultData(String key) {
        // gets country key
        if (key.split("/").length > 1) {
            String[] parts = key.split("/");
            key = parts[0] + "/" + parts[1];
        }

        AddressVerificationNodeData data = get(key);
        if (data == null) {
            throw new RuntimeException("failed to get default data with key " + key);
        }
        return data;
    }
}
