/*
 * Copyright (C) 2019 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.globalactions;

import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;

import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;

import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;

/**
 * Grid-based implementation of the button layout created by the global actions dialog.
 */
public class GlobalActionsColumnLayout extends GlobalActionsLayout {
    private boolean mLastSnap;

    public GlobalActionsColumnLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);

        post(() -> updateSnap());
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @VisibleForTesting
    protected boolean shouldReverseListItems() {
        int rotation = getCurrentRotation();
        if (rotation == ROTATION_NONE) {
            return false;
        }
        if (getCurrentLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
            return rotation == ROTATION_LANDSCAPE;
        }
        return rotation == ROTATION_SEASCAPE;
    }

    @Override
    public void onUpdateList() {
        super.onUpdateList();
        updateChildOrdering();
    }

    private void updateChildOrdering() {
        if (shouldReverseListItems()) {
            getListView().bringToFront();
        } else {
            getSeparatedView().bringToFront();
        }
    }

    /**
     *  Snap this layout to align with the power button.
     */
    @VisibleForTesting
    protected void snapToPowerButton() {
        int offset = getPowerButtonOffsetDistance();
        switch (getCurrentRotation()) {
            case (ROTATION_LANDSCAPE):
                setPadding(offset, 0, 0, 0);
                setGravity(Gravity.LEFT | Gravity.TOP);
                break;
            case (ROTATION_SEASCAPE):
                setPadding(0, 0, offset, 0);
                setGravity(Gravity.RIGHT | Gravity.BOTTOM);
                break;
            default:
                setPadding(0, offset, 0, 0);
                setGravity(Gravity.TOP | Gravity.RIGHT);
                break;
        }
    }

    /**
     *  Detach this layout from snapping to the power button and instead center along that edge.
     */
    @VisibleForTesting
    protected void centerAlongEdge() {
        switch (getCurrentRotation()) {
            case (ROTATION_LANDSCAPE):
                setPadding(0, 0, 0, 0);
                setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP);
                break;
            case (ROTATION_SEASCAPE):
                setPadding(0, 0, 0, 0);
                setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
                break;
            default:
                setPadding(0, 0, 0, 0);
                setGravity(Gravity.CENTER_VERTICAL | Gravity.RIGHT);
                break;
        }
    }

    /**
     * Determines the distance from the top of the screen to the power button.
     */
    @VisibleForTesting
    protected int getPowerButtonOffsetDistance() {
        return Math.round(getContext().getResources().getDimension(
                R.dimen.global_actions_top_padding));
    }

    /**
     * Check whether there is enough extra space below the dialog such that we can offset the top
     * of the dialog from the top of the phone to line it up with the power button, then either
     * snap the dialog to the power button or center it along the edge with snapToPowerButton.
     */
    @VisibleForTesting
    protected boolean shouldSnapToPowerButton() {
        int offsetSize = getPowerButtonOffsetDistance();
        int dialogSize;
        int screenSize;
        View wrapper = getWrapper();
        int rotation = getCurrentRotation();
        if (rotation == ROTATION_NONE) {
            dialogSize = wrapper.getMeasuredHeight();
            screenSize = getMeasuredHeight();
        } else {
            dialogSize = wrapper.getMeasuredWidth();
            screenSize = getMeasuredWidth();
        }
        return dialogSize + offsetSize < screenSize;
    }

    @VisibleForTesting
    protected void updateSnap() {
        boolean snap = shouldSnapToPowerButton();
        if (snap != mLastSnap) {
            if (snap) {
                snapToPowerButton();
            } else {
                centerAlongEdge();
            }
        }
        mLastSnap = snap;
    }

    @VisibleForTesting
    protected float getGridItemSize() {
        return getContext().getResources().getDimension(R.dimen.global_actions_grid_item_height);
    }

    @VisibleForTesting
    protected float getAnimationDistance() {
        return getGridItemSize() / 2;
    }

    @Override
    public float getAnimationOffsetX() {
        if (getCurrentRotation() == ROTATION_NONE) {
            return getAnimationDistance();
        }
        return 0;
    }

    @Override
    public float getAnimationOffsetY() {
        switch (getCurrentRotation()) {
            case ROTATION_LANDSCAPE:
                return -getAnimationDistance();
            case ROTATION_SEASCAPE:
                return getAnimationDistance();
            default: // Portrait
                return 0;
        }
    }
}
