/*
 * 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 com.android.i18n.addressinput.LookupKey.KeyType;
import com.android.i18n.addressinput.LookupKey.ScriptType;

import android.util.Log;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * Controller for an Address Display and is responsible for:
 *
 * <ul> <li>Providing a way to iterate over {@link AddressField}s in a country dependent way.
 * <li>Fetches new address data from the server as needed (based on hierarchy rules of international
 * addresses). <li>Provides {@link FormField} for an {@link AddressField}. A {@link FormField}
 * provides Country specific data for that field. For example, returning the correct label for
 * Administrative Area. </ul>
 *
 * <p> In order for FormController to work properly, it requires two things: <ul> <li>An
 * implementation of {@link AddressDisplayHandler}, which can be set using {@link
 * #initDisplayHandler(AddressDisplayHandler)}. <li>Registering UI widgets which can change using
 * {@link #registerField(AddressField, HasChangeHandlers)}. The registration should happen in
 * constructor of the display. This registration is necessary so the controller can monitor changes
 * and react to them appropriately. For example, a change in Country can cause additional data to be
 * fetched and may cause a change in layout. </ul>
 */
public class FormController {
    // Used to identify the source of a log message.
    private static final String TAG = "FormController";
    // For address hierarchy in lookup key.
    private static final String SLASH_DELIM = "/";
    // For joined values.
    private static final String TILDA_DELIM = "~";
    // For language code info in lookup key (E.g., data/CA--fr).
    private static final String DASH_DELIM = "--";
    // Current user language.

    private final String LANGUAGE_CODE;
    private static final LookupKey ROOT_KEY = FormController.getDataKeyForRoot();
    private static final String DEFAULT_REGION_CODE = "ZZ";
    private final AddressVerificationNodeData DEFAULT_COUNTRY_DATA;

    private static final AddressField[] ADDRESS_HIERARCHY = {
            AddressField.COUNTRY,
            AddressField.ADMIN_AREA,
            AddressField.LOCALITY,
            AddressField.DEPENDENT_LOCALITY
    };

    private ClientData integratedData;
    private String currentCountry;

    /**
     * Constructor that populates this with data. languageCode should be a BCP language code (such
     * as "en" or "zh-Hant") and currentCountry should be an ISO 2-letter region code (such as "GB"
     * or "US").
     */
    public FormController(ClientData integratedData, String languageCode, String currentCountry) {
        Util.checkNotNull(integratedData, "null data not allowed");
        LANGUAGE_CODE = languageCode;
        this.currentCountry = currentCountry;

        AddressData address = new AddressData.Builder().setCountry(DEFAULT_REGION_CODE).build();
        LookupKey defaultCountryKey = getDataKeyFor(address);

        DEFAULT_COUNTRY_DATA = integratedData.getDefaultData(defaultCountryKey.toString());
        Util.checkNotNull(DEFAULT_COUNTRY_DATA,
                "require data for default country key: " + defaultCountryKey);
        this.integratedData = integratedData;
    }

    void setCurrentCountry(String currentCountry) {
        this.currentCountry = currentCountry;
    }

    private ScriptType getScriptType() {
        if (LANGUAGE_CODE != null && Util.isExplicitLatinScript(LANGUAGE_CODE)) {
            return ScriptType.LATIN;
        }
        return ScriptType.LOCAL;
    }

    private static LookupKey getDataKeyForRoot() {
        AddressData address = new AddressData.Builder().build();
        return new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
    }

    LookupKey getDataKeyFor(AddressData address) {
        return new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
    }

    /**
     * Requests data for the input address. This method chains multiple requests together. For
     * example, an address for Mt View, California needs data from "data/US", "data/US/CA", and
     * "data/US/CA/Mt View" to support it. This method will request them one by one (from top level
     * key down to the most granular) and evokes {@link DataLoadListener#dataLoadingEnd} method when
     * all data is collected. If the address is invalid, it will request the first valid child key
     * instead. For example, a request for "data/US/Foo" will end up requesting data for "data/US",
     * "data/US/AL".
     *
     * @param address  the current address.
     * @param listener triggered when requested data for the address is returned.
     */
    public void requestDataForAddress(AddressData address, DataLoadListener listener) {
        Util.checkNotNull(address.getPostalCountry(), "null country not allowed");

        // Gets the key for deepest available node.
        Queue<String> subkeys = new LinkedList<String>();

        for (AddressField field : ADDRESS_HIERARCHY) {
            String value = address.getFieldValue(field);
            if (value == null) {
                break;
            }
            subkeys.add(value);
        }
        if (subkeys.size() == 0) {
            throw new RuntimeException("Need at least country level info");
        }

        if (listener != null) {
            listener.dataLoadingBegin();
        }
        requestDataRecursively(ROOT_KEY, subkeys, listener);
    }

    private void requestDataRecursively(final LookupKey key,
            final Queue<String> subkeys, final DataLoadListener listener) {
        Util.checkNotNull(key, "Null key not allowed");
        Util.checkNotNull(subkeys, "Null subkeys not allowed");

        integratedData.requestData(key, new DataLoadListener() {

            // Override
            public void dataLoadingBegin() {
                Log.w(TAG, "requesting data for key " + key);
            }

            // Override
            public void dataLoadingEnd() {
                List<RegionData> subregions = getRegionData(key);
                if (subregions.isEmpty()) {
                    Log.w(TAG, "recursion ends with key " + key);
                    if (listener != null) {
                        listener.dataLoadingEnd();
                    }
                    // TODO: Should update the selectors here.
                    return;
                } else if (subkeys.size() > 0) {
                    String subkey = subkeys.remove();
                    for (RegionData subregion : subregions) {
                        if (subregion.isValidName(subkey)) {
                            LookupKey nextKey = buildDataLookupKey(key, subregion.getKey());
                            requestDataRecursively(nextKey, subkeys, listener);
                            return;
                        }
                    }
                }

                // Current value in the field is not valid, use the first valid subkey
                // to request more data instead.
                String firstSubkey = subregions.get(0).getKey();
                LookupKey nextKey = buildDataLookupKey(key, firstSubkey);
                Queue<String> emptyList = new LinkedList<String>();
                requestDataRecursively(nextKey, emptyList, listener);
            }
        });
    }

    private LookupKey buildDataLookupKey(LookupKey lookupKey, String subKey) {
        String[] subKeys = lookupKey.toString().split(SLASH_DELIM);
        String languageCodeSubTag =
                (LANGUAGE_CODE == null) ? null : Util.getLanguageSubtag(LANGUAGE_CODE);
        String key = lookupKey.toString() + SLASH_DELIM + subKey;

        // Country level key
        if (subKeys.length == 1 &&
                languageCodeSubTag != null && !isDefaultLanguage(languageCodeSubTag)) {
            key += DASH_DELIM + languageCodeSubTag.toString();
        }
        return new LookupKey.Builder(key).build();
    }

    /**
     * Compares the language subtags of input {@code languageCode} and default language code. For
     * example, "zh-Hant" and "zh" are viewed as identical.
     */
    boolean isDefaultLanguage(String languageCode) {
        if (languageCode == null) {
            return true;
        }
        AddressData addr = new AddressData.Builder().setCountry(currentCountry).build();
        LookupKey lookupKey = getDataKeyFor(addr);
        AddressVerificationNodeData data =
                integratedData.getDefaultData(lookupKey.toString());
        String defaultLanguage = data.get(AddressDataKey.LANG);

        // Current language is not the default language for the country.
        if (Util.trimToNull(defaultLanguage) != null &&
                Util.getLanguageSubtag(languageCode) != Util.getLanguageSubtag(languageCode)) {
            return false;
        }
        return true;
    }

    /**
     * Gets a list of {@link RegionData} for sub-regions for a given key. For example, sub regions
     * for "data/US" are AL/Alabama, AK/Alaska, etc.
     *
     * <p> TODO: It seems more straight forward to return a list of pairs instead of RegionData.
     * Actually, we can remove RegionData since it does not contain anything more than key/value
     * pairs now.
     *
     * @return A list of sub-regions, each sub-region represented by a {@link RegionData}.
     */
    List<RegionData> getRegionData(LookupKey key) {
        if (key.getKeyType() == KeyType.EXAMPLES) {
            throw new RuntimeException("example key not allowed for getting region data");
        }
        Util.checkNotNull(key, "null regionKey not allowed");
        LookupKey normalizedKey = normalizeLookupKey(key);
        List<RegionData> results = new ArrayList<RegionData>();

        // Root key.
        if (normalizedKey.equals(ROOT_KEY)) {
            AddressVerificationNodeData data =
                    integratedData.getDefaultData(normalizedKey.toString());
            String[] countries = splitData(data.get(AddressDataKey.COUNTRIES));
            for (int i = 0; i < countries.length; i++) {
                RegionData rd = new RegionData.Builder()
                        .setKey(countries[i])
                        .setName(countries[i])
                        .build();
                results.add(rd);
            }
            return results;
        }

        AddressVerificationNodeData data =
                integratedData.get(normalizedKey.toString());
        if (data != null) {
            String[] keys = splitData(data.get(AddressDataKey.SUB_KEYS));
            String[] names = (getScriptType() == ScriptType.LOCAL)
                    ? splitData(data.get(AddressDataKey.SUB_NAMES))
                    : splitData(data.get(AddressDataKey.SUB_LNAMES));

            for (int i = 0; i < keys.length; i++) {
                RegionData rd =
                        new RegionData.Builder()
                                .setKey(keys[i])
                                .setName((i < names.length) ? names[i] : keys[i])
                                .build();
                results.add(rd);
            }
        }
        return results;
    }

    /**
     * Split a '~' delimited string into an array of strings. This method is null tolerant and
     * considers an empty string to contain no elements.
     *
     * @param raw The data to split
     * @return an array of strings
     */
    private String[] splitData(String raw) {
        if (raw == null || raw.length() == 0) {
            return new String[]{};
        }
        return raw.split(TILDA_DELIM);
    }

    private String getSubKey(LookupKey parentKey, String name) {
        for (RegionData subRegion : getRegionData(parentKey)) {
            if (subRegion.isValidName(name)) {
                return subRegion.getKey();
            }
        }
        return null;
    }

    /**
     * Normalizes {@code key} by replacing field values with sub-keys. For example, California is
     * replaced with CA. The normalization goes from top (country) to bottom (dependent locality)
     * and if any field value is empty, unknown, or invalid, it will stop and return whatever it
     * gets. For example, a key "data/US/California/foobar/kar" will be normalized into
     * "data/US/CA/foobar/kar" since "foobar" is unknown. This method supports only key of
     * {@link KeyType#DATA} type.
     *
     * @return normalized {@link LookupKey}.
     */
    private LookupKey normalizeLookupKey(LookupKey key) {
        Util.checkNotNull(key);
        if (key.getKeyType() != KeyType.DATA) {
            throw new RuntimeException("Only DATA keyType is supported");
        }

        String subStr[] = key.toString().split(SLASH_DELIM);

        // Root key does not need to be normalized.
        if (subStr.length < 2) {
            return key;
        }

        StringBuilder sb = new StringBuilder(subStr[0]);
        for (int i = 1; i < subStr.length; ++i) {
            // Strips the language code if contained.
            String languageCode = null;
            if (i == 1 && subStr[i].contains(DASH_DELIM)) {
                String[] s = subStr[i].split(DASH_DELIM);
                subStr[i] = s[0];
                languageCode = s[1];
            }

            String normalizedSubKey = getSubKey(new LookupKey.Builder(sb.toString()).build(),
                    subStr[i]);

            // Can't find normalized sub-key; assembles the lookup key with the
            // remaining sub-keys and returns it.
            if (normalizedSubKey == null) {
                for (; i < subStr.length; ++i) {
                    sb.append(SLASH_DELIM).append(subStr[i]);
                }
                break;
            }
            sb.append(SLASH_DELIM).append(normalizedSubKey);
            if (languageCode != null) {
                sb.append(DASH_DELIM).append(languageCode);
            }
        }
        return new LookupKey.Builder(sb.toString()).build();
    }
}
