/*
 * Copyright (C) 2010 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 android.preference;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;

/**
 * @hide
 *
 * @deprecated Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
 *      <a href="{@docRoot}reference/androidx/preference/package-summary.html">
 *      Preference Library</a> for consistent behavior across all devices. For more information on
 *      using the AndroidX Preference Library see
 *      <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>.
 */
@Deprecated
public class PreferenceFrameLayout extends FrameLayout {
    private static final int DEFAULT_BORDER_TOP = 0;
    private static final int DEFAULT_BORDER_BOTTOM = 0;
    private static final int DEFAULT_BORDER_LEFT = 0;
    private static final int DEFAULT_BORDER_RIGHT = 0;
    private final int mBorderTop;
    private final int mBorderBottom;
    private final int mBorderLeft;
    private final int mBorderRight;
    private boolean mPaddingApplied;

    public PreferenceFrameLayout(Context context) {
        this(context, null);
    }

    public PreferenceFrameLayout(Context context, AttributeSet attrs) {
        this(context, attrs, com.android.internal.R.attr.preferenceFrameLayoutStyle);
    }

    public PreferenceFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public PreferenceFrameLayout(
            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        final TypedArray a = context.obtainStyledAttributes(attrs,
                com.android.internal.R.styleable.PreferenceFrameLayout, defStyleAttr, defStyleRes);

        float density = context.getResources().getDisplayMetrics().density;
        int defaultBorderTop = (int) (density * DEFAULT_BORDER_TOP + 0.5f);
        int defaultBottomPadding = (int) (density * DEFAULT_BORDER_BOTTOM + 0.5f);
        int defaultLeftPadding = (int) (density * DEFAULT_BORDER_LEFT + 0.5f);
        int defaultRightPadding = (int) (density * DEFAULT_BORDER_RIGHT + 0.5f);

        mBorderTop = a.getDimensionPixelSize(
                com.android.internal.R.styleable.PreferenceFrameLayout_borderTop,
                defaultBorderTop);
        mBorderBottom = a.getDimensionPixelSize(
                com.android.internal.R.styleable.PreferenceFrameLayout_borderBottom,
                defaultBottomPadding);
        mBorderLeft = a.getDimensionPixelSize(
                com.android.internal.R.styleable.PreferenceFrameLayout_borderLeft,
                defaultLeftPadding);
        mBorderRight = a.getDimensionPixelSize(
                com.android.internal.R.styleable.PreferenceFrameLayout_borderRight,
                defaultRightPadding);

        a.recycle();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

    @Override
    public void addView(View child) {
        int borderTop = getPaddingTop();
        int borderBottom = getPaddingBottom();
        int borderLeft = getPaddingLeft();
        int borderRight = getPaddingRight();

        android.view.ViewGroup.LayoutParams params = child.getLayoutParams();
        LayoutParams layoutParams = params instanceof PreferenceFrameLayout.LayoutParams
            ? (PreferenceFrameLayout.LayoutParams) child.getLayoutParams() : null;
        // Check on the id of the child before adding it.
        if (layoutParams != null && layoutParams.removeBorders) {
            if (mPaddingApplied) {
                borderTop -= mBorderTop;
                borderBottom -= mBorderBottom;
                borderLeft -= mBorderLeft;
                borderRight -= mBorderRight;
                mPaddingApplied = false;
            }
        } else {
            // Add the padding to the view group after determining if the
            // padding already exists.
            if (!mPaddingApplied) {
                borderTop += mBorderTop;
                borderBottom += mBorderBottom;
                borderLeft += mBorderLeft;
                borderRight += mBorderRight;
                mPaddingApplied = true;
            }
        }

        int previousTop = getPaddingTop();
        int previousBottom = getPaddingBottom();
        int previousLeft = getPaddingLeft();
        int previousRight = getPaddingRight();
        if (previousTop != borderTop || previousBottom != borderBottom
                || previousLeft != borderLeft || previousRight != borderRight) {
            setPadding(borderLeft, borderTop, borderRight, borderBottom);
        }

        super.addView(child);
    }

    public static class LayoutParams extends FrameLayout.LayoutParams {
        public boolean removeBorders = false;
        /**
         * {@inheritDoc}
         */
        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);

            TypedArray a = c.obtainStyledAttributes(attrs,
                    com.android.internal.R.styleable.PreferenceFrameLayout_Layout);
            removeBorders = a.getBoolean(
                    com.android.internal.R.styleable.PreferenceFrameLayout_Layout_layout_removeBorders,
                    false);
            a.recycle();
        }

        /**
         * {@inheritDoc}
         */
        public LayoutParams(int width, int height) {
            super(width, height);
        }
    }
}