/*
 * 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.statusbar.phone;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ScrollView;

/**
 * A scroll view which can be observed for scroll change events.
 */
public class ObservableScrollView extends ScrollView {

    private Listener mListener;
    private int mLastOverscrollAmount;
    private boolean mTouchEnabled = true;
    private boolean mHandlingTouchEvent;
    private float mLastX;
    private float mLastY;
    private boolean mBlockFlinging;
    private boolean mTouchCancelled;

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

    public void setListener(Listener listener) {
        mListener = listener;
    }

    public void setTouchEnabled(boolean touchEnabled) {
        mTouchEnabled = touchEnabled;
    }

    public boolean isScrolledToBottom() {
        return getScrollY() == getMaxScrollY();
    }

    public boolean isHandlingTouchEvent() {
        return mHandlingTouchEvent;
    }

    private int getMaxScrollY() {
        int scrollRange = 0;
        if (getChildCount() > 0) {
            View child = getChildAt(0);
            scrollRange = Math.max(0,
                    child.getHeight() - (getHeight() - mPaddingBottom - mPaddingTop));
        }
        return scrollRange;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        mHandlingTouchEvent = true;
        mLastX = ev.getX();
        mLastY = ev.getY();
        boolean result = super.onTouchEvent(ev);
        mHandlingTouchEvent = false;
        return result;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        mHandlingTouchEvent = true;
        mLastX = ev.getX();
        mLastY = ev.getY();
        boolean result = super.onInterceptTouchEvent(ev);
        mHandlingTouchEvent = false;
        return result;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            if (!mTouchEnabled) {
                mTouchCancelled = true;
                return false;
            }
            mTouchCancelled = false;
        } else if (mTouchCancelled) {
            return false;
        } else if (!mTouchEnabled) {
            MotionEvent cancel = MotionEvent.obtain(ev);
            cancel.setAction(MotionEvent.ACTION_CANCEL);
            super.dispatchTouchEvent(cancel);
            cancel.recycle();
            mTouchCancelled = true;
            return false;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mListener != null) {
            mListener.onScrollChanged();
        }
    }

    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY,
            int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY,
            boolean isTouchEvent) {
        mLastOverscrollAmount = Math.max(0, scrollY + deltaY - getMaxScrollY());
        return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY,
                        maxOverScrollX, maxOverScrollY, isTouchEvent);
    }

    public void setBlockFlinging(boolean blockFlinging) {
        mBlockFlinging = blockFlinging;
    }

    @Override
    public void fling(int velocityY) {
        if (!mBlockFlinging) {
            super.fling(velocityY);
        }
    }

    @Override
    protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
        super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
        if (mListener != null && mLastOverscrollAmount > 0) {
            mListener.onOverscrolled(mLastX, mLastY, mLastOverscrollAmount);
        }
    }

    public interface Listener {
        void onScrollChanged();
        void onOverscrolled(float lastX, float lastY, int amount);
    }
}
