/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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.launcher3.config;

import static androidx.core.util.Preconditions.checkNotNull;

import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;

import androidx.annotation.GuardedBy;
import androidx.annotation.Keep;
import androidx.annotation.VisibleForTesting;

import com.android.launcher3.Utilities;

import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * Defines a set of flags used to control various launcher behaviors.
 *
 * <p>All the flags should be defined here with appropriate default values.
 *
 * <p>This class is kept package-private to prevent direct access.
 */
@Keep
abstract class BaseFlags {

    private static final Object sLock = new Object();
    @GuardedBy("sLock")
    private static final List<TogglableFlag> sFlags = new ArrayList<>();

    static final String FLAGS_PREF_NAME = "featureFlags";

    BaseFlags() {
        throw new UnsupportedOperationException("Don't instantiate BaseFlags");
    }

    public static boolean showFlagTogglerUi(Context context) {
        return Utilities.IS_DEBUG_DEVICE &&
                Settings.Global.getInt(context.getApplicationContext().getContentResolver(),
                        Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
    }

    public static final boolean IS_DOGFOOD_BUILD = false;

    // When enabled the promise icon is visible in all apps while installation an app.
    public static final boolean LAUNCHER3_PROMISE_APPS_IN_ALL_APPS = false;

    // Enable moving the QSB on the 0th screen of the workspace
    public static final boolean QSB_ON_FIRST_SCREEN = true;

    public static final TogglableFlag EXAMPLE_FLAG = new TogglableFlag("EXAMPLE_FLAG", true,
            "An example flag that doesn't do anything. Useful for testing");

    //Feature flag to enable pulling down navigation shade from workspace.
    public static final boolean PULL_DOWN_STATUS_BAR = true;

    // When true, custom widgets are loaded using CustomWidgetParser.
    public static final boolean ENABLE_CUSTOM_WIDGETS = false;

    // Features to control Launcher3Go behavior
    public static final boolean GO_DISABLE_WIDGETS = false;

    // When enabled shows a work profile tab in all apps
    public static final boolean ALL_APPS_TABS_ENABLED = true;

    // When true, overview shows screenshots in the orientation they were taken rather than
    // trying to make them fit the orientation the device is in.
    public static final boolean OVERVIEW_USE_SCREENSHOT_ORIENTATION = true;

    public static final ToggleableGlobalSettingsFlag STYLE_WALLPAPER
            = new ToggleableGlobalSettingsFlag("STYLE_WALLPAPER", false,
            "Direct users to the new ThemePicker based WallpaperPicker");

    /**
     * Feature flag to handle define config changes dynamically instead of killing the process.
     */
    public static final TogglableFlag APPLY_CONFIG_AT_RUNTIME = new TogglableFlag(
            "APPLY_CONFIG_AT_RUNTIME", true, "Apply display changes dynamically");

    public static final TogglableFlag QUICKSTEP_SPRINGS = new TogglableFlag("QUICKSTEP_SPRINGS",
            false, "Enable springs for quickstep animations");

    public static final TogglableFlag ADAPTIVE_ICON_WINDOW_ANIM = new TogglableFlag(
            "ADAPTIVE_ICON_WINDOW_ANIM", true,
            "Use adaptive icons for window animations.");

    public static final TogglableFlag ENABLE_QUICKSTEP_LIVE_TILE = new TogglableFlag(
            "ENABLE_QUICKSTEP_LIVE_TILE", false, "Enable live tile in Quickstep overview");

    public static final ToggleableGlobalSettingsFlag SWIPE_HOME
            = new ToggleableGlobalSettingsFlag("SWIPE_HOME", false,
            "Swiping up on the nav bar goes home. Swipe and hold goes to recent apps.");

    public static final TogglableFlag ENABLE_HINTS_IN_OVERVIEW = new TogglableFlag(
            "ENABLE_HINTS_IN_OVERVIEW", false,
            "Show chip hints and gleams on the overview screen");

    public static final TogglableFlag ENABLE_ASSISTANT_GESTURE = new ToggleableGlobalSettingsFlag(
            "ENABLE_ASSISTANT_GESTURE", false,
            "Enable swipe up from the bottom right corner to start assistant");

    public static void initialize(Context context) {
        // Avoid the disk read for user builds
        if (Utilities.IS_DEBUG_DEVICE) {
            synchronized (sLock) {
                for (TogglableFlag flag : sFlags) {
                    flag.initialize(context);
                }
            }
        }
    }

    static List<TogglableFlag> getTogglableFlags() {
        // By Java Language Spec 12.4.2
        // https://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2, the
        // TogglableFlag instances on BaseFlags will be created before those on the FeatureFlags
        // subclass. This code handles flags that are redeclared in FeatureFlags, ensuring the
        // FeatureFlags one takes priority.
        SortedMap<String, TogglableFlag> flagsByKey = new TreeMap<>();
        synchronized (sLock) {
            for (TogglableFlag flag : sFlags) {
                flagsByKey.put(flag.key, flag);
            }
        }
        return new ArrayList<>(flagsByKey.values());
    }

    public static class TogglableFlag {
        private final String key;
        private final boolean defaultValue;
        private final String description;
        private boolean currentValue;

        TogglableFlag(
                String key,
                boolean defaultValue,
                String description) {
            this.key = checkNotNull(key);
            this.currentValue = this.defaultValue = defaultValue;
            this.description = checkNotNull(description);
            synchronized (sLock) {
                sFlags.add(this);
            }
        }

        /** Set the value of this flag. This should only be used in tests. */
        @VisibleForTesting
        void setForTests(boolean value) {
            currentValue = value;
        }

        @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
        public String getKey() {
            return key;
        }
        void initialize(Context context) {
            currentValue = getFromStorage(context, defaultValue);
        }

        void updateStorage(Context context, boolean value) {
            SharedPreferences.Editor editor = context.getSharedPreferences(FLAGS_PREF_NAME,
                    Context.MODE_PRIVATE).edit();
            if (value == defaultValue) {
                editor.remove(key).apply();
            } else {
                editor.putBoolean(key, value).apply();
            }
        }

        boolean getFromStorage(Context context, boolean defaultValue) {
            return context.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE)
                    .getBoolean(key, defaultValue);
        }

        boolean getDefaultValue() {
            return defaultValue;
        }

        /** Returns the value of the flag at process start, including any overrides present. */
        public boolean get() {
            return currentValue;
        }

        String getDescription() {
            return description;
        }

        @Override
        public String toString() {
            return "TogglableFlag{"
                    + "key=" + key + ", "
                    + "defaultValue=" + defaultValue + ", "
                    + "description=" + description
                    + "}";
        }

        @Override
        public boolean equals(Object o) {
            if (o == this) {
                return true;
            }
            if (o instanceof TogglableFlag) {
                TogglableFlag that = (TogglableFlag) o;
                return (this.key.equals(that.getKey()))
                        && (this.defaultValue == that.getDefaultValue())
                        && (this.description.equals(that.getDescription()));
            }
            return false;
        }

        @Override
        public int hashCode() {
            int h$ = 1;
            h$ *= 1000003;
            h$ ^= key.hashCode();
            h$ *= 1000003;
            h$ ^= defaultValue ? 1231 : 1237;
            h$ *= 1000003;
            h$ ^= description.hashCode();
            return h$;
        }
    }

    /**
     * Stores the FeatureFlag's value in Settings.Global instead of our SharedPrefs.
     * This is useful if we want to be able to control this flag from another process.
     */
    public static final class ToggleableGlobalSettingsFlag extends TogglableFlag {
        private ContentResolver contentResolver;

        ToggleableGlobalSettingsFlag(String key, boolean defaultValue, String description) {
            super(key, defaultValue, description);
        }

        @Override
        public void initialize(Context context) {
            contentResolver = context.getContentResolver();
            contentResolver.registerContentObserver(Settings.Global.getUriFor(getKey()), true,
                    new ContentObserver(new Handler(Looper.getMainLooper())) {
                        @Override
                        public void onChange(boolean selfChange) {
                            superInitialize(context);
                    }});
            superInitialize(context);
        }

        private void superInitialize(Context context) {
            super.initialize(context);
        }

        @Override
        void updateStorage(Context context, boolean value) {
            if (contentResolver == null) {
                return;
            }
            Settings.Global.putInt(contentResolver, getKey(), value ? 1 : 0);
        }

        @Override
        boolean getFromStorage(Context context, boolean defaultValue) {
            if (contentResolver == null) {
                return defaultValue;
            }
            return Settings.Global.getInt(contentResolver, getKey(), defaultValue ? 1 : 0) == 1;
        }
    }
}
