/*
 * Copyright (C) 2014 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.systemui.recents;

import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import com.android.systemui.R;


/** A static Recents configuration for the current context
 * NOTE: We should not hold any references to a Context from a static instance */
public class RecentsConfiguration {
    static RecentsConfiguration sInstance;

    DisplayMetrics mDisplayMetrics;

    public Rect systemInsets = new Rect();
    public Rect displayRect = new Rect();

    boolean isLandscape;
    boolean transposeSearchLayoutWithOrientation;
    int searchBarAppWidgetId = -1;

    public float animationPxMovementPerSecond;

    public Interpolator fastOutSlowInInterpolator;
    public Interpolator fastOutLinearInInterpolator;
    public Interpolator linearOutSlowInInterpolator;

    public int filteringCurrentViewsMinAnimDuration;
    public int filteringNewViewsMinAnimDuration;

    public int taskStackScrollDismissInfoPaneDistance;
    public int taskStackMaxDim;
    public float taskStackWidthPaddingPct;
    public int taskStackTopPaddingPx;

    public int taskViewInfoPaneAnimDuration;
    public int taskViewRemoveAnimDuration;
    public int taskViewRemoveAnimTranslationXPx;
    public int taskViewTranslationZMinPx;
    public int taskViewTranslationZIncrementPx;
    public int taskViewShadowOutlineBottomInsetPx;
    public int taskViewRoundedCornerRadiusPx;
    public int taskViewHighlightPx;

    public int searchBarSpaceHeightPx;

    public int taskBarViewDefaultBackgroundColor;
    public int taskBarViewDefaultTextColor;
    public int taskBarViewLightTextColor;
    public int taskBarViewDarkTextColor;
    public int taskBarViewHighlightColor;

    public int taskBarEnterAnimDuration;
    public int taskBarExitAnimDuration;

    public boolean launchedFromAltTab;
    public boolean launchedWithThumbnailAnimation;

    public boolean developerOptionsEnabled;

    /** Private constructor */
    private RecentsConfiguration() {}

    /** Updates the configuration to the current context */
    public static RecentsConfiguration reinitialize(Context context) {
        if (sInstance == null) {
            sInstance = new RecentsConfiguration();
        }
        sInstance.update(context);
        return sInstance;
    }

    /** Returns the current recents configuration */
    public static RecentsConfiguration getInstance() {
        return sInstance;
    }

    /** Updates the state, given the specified context */
    void update(Context context) {
        Resources res = context.getResources();
        DisplayMetrics dm = res.getDisplayMetrics();
        mDisplayMetrics = dm;

        isLandscape = res.getConfiguration().orientation ==
                Configuration.ORIENTATION_LANDSCAPE;
        transposeSearchLayoutWithOrientation =
                res.getBoolean(R.bool.recents_transpose_search_layout_with_orientation);
        if (Console.Enabled) {
            Console.log(Constants.Log.UI.MeasureAndLayout,
                    "[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait",
                    Console.AnsiGreen);
        }

        displayRect.set(0, 0, dm.widthPixels, dm.heightPixels);
        animationPxMovementPerSecond =
                res.getDimensionPixelSize(R.dimen.recents_animation_movement_in_dps_per_second);
        filteringCurrentViewsMinAnimDuration =
                res.getInteger(R.integer.recents_filter_animate_current_views_min_duration);
        filteringNewViewsMinAnimDuration =
                res.getInteger(R.integer.recents_filter_animate_new_views_min_duration);

        taskStackScrollDismissInfoPaneDistance = res.getDimensionPixelSize(
                R.dimen.recents_task_stack_scroll_dismiss_info_pane_distance);
        taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);

        TypedValue widthPaddingPctValue = new TypedValue();
        res.getValue(R.dimen.recents_stack_width_padding_percentage, widthPaddingPctValue, true);
        taskStackWidthPaddingPct = widthPaddingPctValue.getFloat();
        taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding);

        taskViewInfoPaneAnimDuration =
                res.getInteger(R.integer.recents_animate_task_view_info_pane_duration);
        taskViewRemoveAnimDuration =
                res.getInteger(R.integer.recents_animate_task_view_remove_duration);
        taskViewRemoveAnimTranslationXPx =
                res.getDimensionPixelSize(R.dimen.recents_task_view_remove_anim_translation_x);
        taskViewRoundedCornerRadiusPx =
                res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
        taskViewHighlightPx = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight);
        taskViewTranslationZMinPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min);
        taskViewTranslationZIncrementPx =
                res.getDimensionPixelSize(R.dimen.recents_task_view_z_increment);
        taskViewShadowOutlineBottomInsetPx =
                res.getDimensionPixelSize(R.dimen.recents_task_view_shadow_outline_bottom_inset);

        searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height);

        taskBarViewDefaultBackgroundColor =
                res.getColor(R.color.recents_task_bar_default_background_color);
        taskBarViewDefaultTextColor =
                res.getColor(R.color.recents_task_bar_default_text_color);
        taskBarViewLightTextColor =
                res.getColor(R.color.recents_task_bar_light_text_color);
        taskBarViewDarkTextColor =
                res.getColor(R.color.recents_task_bar_dark_text_color);
        taskBarViewHighlightColor =
                res.getColor(R.color.recents_task_bar_highlight_color);

        taskBarEnterAnimDuration =
                res.getInteger(R.integer.recents_animate_task_bar_enter_duration);
        taskBarExitAnimDuration =
                res.getInteger(R.integer.recents_animate_task_bar_exit_duration);

        fastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
                        com.android.internal.R.interpolator.fast_out_slow_in);
        fastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
                com.android.internal.R.interpolator.fast_out_linear_in);
        linearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
                com.android.internal.R.interpolator.linear_out_slow_in);

        // Check if the developer options are enabled
        ContentResolver cr = context.getContentResolver();
        developerOptionsEnabled = Settings.Global.getInt(cr,
                Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;

        // Update the search widget id
        SharedPreferences settings = context.getSharedPreferences(context.getPackageName(), 0);
        searchBarAppWidgetId = settings.getInt(Constants.Values.App.Key_SearchAppWidgetId, -1);
    }

    /** Updates the system insets */
    public void updateSystemInsets(Rect insets) {
        systemInsets.set(insets);
    }

    /** Updates the search bar app widget */
    public void updateSearchBarAppWidgetId(Context context, int appWidgetId) {
        searchBarAppWidgetId = appWidgetId;
        SharedPreferences settings = context.getSharedPreferences(context.getPackageName(), 0);
        settings.edit().putInt(Constants.Values.App.Key_SearchAppWidgetId,
                appWidgetId).apply();
    }

    /** Called when the configuration has changed, and we want to reset any configuration specific
     * members. */
    public void updateOnConfigurationChange() {
        launchedFromAltTab = false;
        launchedWithThumbnailAnimation = false;
    }

    /** Returns whether the search bar app widget exists */
    public boolean hasSearchBarAppWidget() {
        return searchBarAppWidgetId >= 0;
    }

    /**
     * Returns the task stack bounds in the current orientation. These bounds do not account for
     * the system insets.
     */
    public void getTaskStackBounds(int width, int height, Rect taskStackBounds) {
        if (hasSearchBarAppWidget()) {
            Rect searchBarBounds = new Rect();
            getSearchBarBounds(width, height, searchBarBounds);
            if (isLandscape && transposeSearchLayoutWithOrientation) {
                // In landscape, the search bar appears on the left, so shift the task rect right
                taskStackBounds.set(searchBarBounds.width(), 0, width, height);
            } else {
                // In portrait, the search bar appears on the top, so shift the task rect below
                taskStackBounds.set(0, searchBarBounds.height(), width, height);
            }
        } else {
            taskStackBounds.set(0, 0, width, height);
        }
    }

    /**
     * Returns the search bar bounds in the current orientation.  These bounds do not account for
     * the system insets.
     */
    public void getSearchBarBounds(int width, int height, Rect searchBarSpaceBounds) {
        // Return empty rects if search is not enabled
        if (!Constants.DebugFlags.App.EnableSearchLayout) {
            searchBarSpaceBounds.set(0, 0, 0, 0);
            return;
        }

        if (isLandscape && transposeSearchLayoutWithOrientation) {
            // In landscape, the search bar appears on the left
            searchBarSpaceBounds.set(0, 0, searchBarSpaceHeightPx, height);
        } else {
            // In portrait, the search bar appears on the top
            searchBarSpaceBounds.set(0, 0, width, searchBarSpaceHeightPx);
        }
    }

    /** Converts from DPs to PXs */
    public int pxFromDp(float size) {
        return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                size, mDisplayMetrics));
    }
    /** Converts from SPs to PXs */
    public int pxFromSp(float size) {
        return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                size, mDisplayMetrics));
    }
}
