package org.wikipedia.language;

import android.content.Context;
import android.text.TextUtils;

import org.apache.commons.lang3.StringUtils;
import org.wikipedia.WikipediaApp;
import org.wikipedia.settings.Prefs;
import org.wikipedia.util.StringUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.wikipedia.language.AppLanguageLookUpTable.TEST_LANGUAGE_CODE;

/** Language lookup and state management for the application language and most recently used article
 * and application languages. */
public class AppLanguageState {
    @NonNull
    private final AppLanguageLookUpTable appLanguageLookUpTable;

    // The language code used by the app when the article language is unspecified. It's possible for
    // this code to be unsupported if the languages supported changes.
    // TODO: Remove in April 2019
    @Nullable
    private String appLanguageCode;

    // Language codes that have been explicitly chosen by the user in most recently used order. This
    // list includes both app and article languages.
    @NonNull
    private final List<String> mruLanguageCodes;

    @NonNull
    private final List<String> appLanguageCodes;

    public AppLanguageState(@NonNull Context context) {
        appLanguageLookUpTable = new AppLanguageLookUpTable(context);
        appLanguageCode = Prefs.getAppLanguageCode();
        mruLanguageCodes = new ArrayList<>(StringUtil.csvToList(defaultString(Prefs.getMruLanguageCodeCsv())));
        appLanguageCodes = new ArrayList<>(StringUtil.csvToList(defaultString(Prefs.getAppLanguageCodeCsv())));
        initAppLanguageCodes();
    }

    @NonNull
    public List<String> getAppLanguageCodes() {
        if (appLanguageCodes.isEmpty()) {
            // very bad, should not happen.
            initAppLanguageCodes();
        }
        return appLanguageCodes;
    }

    public void addAppLanguageCode(@Nullable String code) {
        appLanguageCodes.remove(code);
        appLanguageCodes.add(code);
        Prefs.setAppLanguageCodeCsv(StringUtil.listToCsv(appLanguageCodes));
        WikipediaApp.getInstance().resetWikiSite();
    }

    public void setAppLanguageCodes(@NonNull List<String> codes) {
        appLanguageCodes.clear();
        for (String code : codes) {
            if (!TextUtils.isEmpty(code)) {
                appLanguageCodes.add(code);
            }
        }
        Prefs.setAppLanguageCodeCsv(StringUtil.listToCsv(appLanguageCodes));
        WikipediaApp.getInstance().resetWikiSite();
    }

    public void removeAppLanguageCodes(@NonNull List<String> codes) {
        if (appLanguageCodes.size() > 1) {
            appLanguageCodes.removeAll(codes);
            Prefs.setAppLanguageCodeCsv(StringUtil.listToCsv(appLanguageCodes));
        }
    }

    private void initAppLanguageCodes() {
        if (appLanguageCodes.isEmpty()) {
            if (!TextUtils.isEmpty(appLanguageCode)) {
                addAppLanguageCode(appLanguageCode);
            } else if (Prefs.isInitialOnboardingEnabled()) {
                setAppLanguageCodes(getRemainingAvailableLanguageCodes());
            } else {
                // If user has never changed app language before
                addAppLanguageCode(getSystemLanguageCode());
            }
        }
    }

    @NonNull
    public String getAppLanguageCode() {
        return getAppLanguageCodes().get(0);
    }

    @NonNull public List<String> getRemainingAvailableLanguageCodes() {
        List<String> list = new ArrayList<>();
        for (String code : LanguageUtil.getAvailableLanguages()) {
            if (!appLanguageCodes.contains(code)
                    && appLanguageLookUpTable.isSupportedCode(code)) {
                list.add(code);
            }
        }
        return list;
    }

    @NonNull public String getSystemLanguageCode() {
        String code = LanguageUtil.localeToWikiLanguageCode(Locale.getDefault());
        return appLanguageLookUpTable.isSupportedCode(code)
                ? code : AppLanguageLookUpTable.FALLBACK_LANGUAGE_CODE;
    }

    @NonNull public List<String> getMruLanguageCodes() {
        return mruLanguageCodes;
    }

    public void addMruLanguageCode(@Nullable String code) {
        mruLanguageCodes.remove(code);
        mruLanguageCodes.add(0, code);
        Prefs.setMruLanguageCodeCsv(StringUtil.listToCsv(mruLanguageCodes));
    }

    /** @return All app supported languages in MRU order. */
    public List<String> getAppMruLanguageCodes() {
        List<String> codes = new ArrayList<>(appLanguageLookUpTable.getCodes());
        int insertIndex = 0;
        for (String code : mruLanguageCodes) {
            if (codes.contains(code)) {
                codes.remove(code);
                codes.add(insertIndex, code);
                ++insertIndex;
            }
        }
        if (!Prefs.isShowDeveloperSettingsEnabled()) {
            codes.remove(TEST_LANGUAGE_CODE);
        }
        return codes;
    }

    /** @return English name if app language is supported. */
    @Nullable
    public String getAppLanguageCanonicalName(@Nullable String code) {
        return appLanguageLookUpTable.getCanonicalName(code);
    }

    @Nullable
    public String getAppLanguageLocalizedNames() {
        List<String> list = new ArrayList<>();
        for (String code : getAppLanguageCodes()) {
            list.add(StringUtils.capitalize(getAppLanguageLocalizedName(code)));
        }
        return TextUtils.join(", ", list);
    }

    /** @return Native name if app language is supported. */
    @Nullable
    public String getAppLanguageLocalizedName(@Nullable String code) {
        return appLanguageLookUpTable.getLocalizedName(code);
    }
}

@@ -793,265 +793,8 @@
 e;%0A%0A
-    // The language code used by the app when the article language is unspecified. It's possible for%0A    // this code to be unsupported if the languages supported changes.%0A    // TODO: Remove in April 2019%0A    @Nullable%0A    private String appLanguageCode;%0A%0A
     
@@ -1199,62 +1199,8 @@
 t);%0A
-        appLanguageCode = Prefs.getAppLanguageCode();%0A
     
@@ -2708,123 +2708,8 @@
  if 
-(!TextUtils.isEmpty(appLanguageCode)) %7B%0A                addAppLanguageCode(appLanguageCode);%0A            %7D else if 
 (Pre

Remove old app language code logic