/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.taobao.weex.ui.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;
import android.support.v4.view.NestedScrollingChild;
import android.support.v4.view.NestedScrollingChildHelper;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ScrollView;

import com.taobao.weex.common.WXThread;
import com.taobao.weex.ui.component.WXComponent;
import com.taobao.weex.ui.component.WXScroller;
import com.taobao.weex.ui.view.gesture.WXGesture;
import com.taobao.weex.ui.view.gesture.WXGestureObservable;
import com.taobao.weex.utils.WXLogUtils;
import com.taobao.weex.utils.WXReflectionUtils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;


/**
 * Custom-defined scrollView
 */
public class WXScrollView extends ScrollView implements Callback, IWXScroller,
                                                        WXGestureObservable,NestedScrollingChild {

  private NestedScrollingChildHelper childHelper;
  private float ox;
  private float oy;
  private int[] consumed = new int[2];
  private int[] offsetInWindow = new int[2];

  int mScrollX;
  int mScrollY;
  private WXGesture wxGesture;
  private List<WXScrollViewListener> mScrollViewListeners;
  private WXScroller mWAScroller;
  //sticky
  private View mCurrentStickyView;
  private boolean mRedirectTouchToStickyView;
  private int mStickyOffset;
  private boolean mHasNotDoneActionDown = true;
  @SuppressLint("HandlerLeak")
  private Handler mScrollerTask;
  private int mInitialPosition;
  private int mCheckTime = 100;
  /**
   * The location of mCurrentStickyView
   */
  private int[] mStickyP = new int[2];
  /**
   * Location of the scrollView
   */
  private Rect mScrollRect;
  private int[] stickyScrollerP = new int[2];
  private int[] stickyViewP = new int[2];
  private boolean scrollable = true;

  public WXScrollView(Context context) {
    super(context);
    mScrollViewListeners = new ArrayList<>();
    init();
    try {
      WXReflectionUtils.setValue(this, "mMinimumVelocity", 5);
    } catch (Exception e) {
      WXLogUtils.e("[WXScrollView] WXScrollView: ", e);
    }
  }

  private void init() {
    setWillNotDraw(false);
    startScrollerTask();
    setOverScrollMode(View.OVER_SCROLL_NEVER);
    childHelper = new NestedScrollingChildHelper(this);
    childHelper.setNestedScrollingEnabled(true);
  }

  public void startScrollerTask() {
    if (mScrollerTask == null) {
      mScrollerTask = new Handler(WXThread.secure(this));
    }
    mInitialPosition = getScrollY();
    mScrollerTask.sendEmptyMessageDelayed(0, mCheckTime);
  }

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

  public WXScrollView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    setOverScrollMode(View.OVER_SCROLL_NEVER);
  }

  /**
   * Add listener for scrollView.
   */
  public void addScrollViewListener(WXScrollViewListener scrollViewListener) {
    if (!mScrollViewListeners.contains(scrollViewListener)) {
      mScrollViewListeners.add(scrollViewListener);
    }
  }

  public void removeScrollViewListener(WXScrollViewListener scrollViewListener) {
    mScrollViewListeners.remove(scrollViewListener);
  }

  @Override
  public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
      mRedirectTouchToStickyView = true;
    }

    if (mRedirectTouchToStickyView) {
      mRedirectTouchToStickyView = mCurrentStickyView != null;

      if (mRedirectTouchToStickyView) {
        mRedirectTouchToStickyView = ev.getY() <= mCurrentStickyView.getHeight()
                                     && ev.getX() >= mCurrentStickyView.getLeft()
                                     && ev.getX() <= mCurrentStickyView.getRight();
      }
    }

    if (mRedirectTouchToStickyView) {
      if (mScrollRect == null) {
        mScrollRect = new Rect();
        getGlobalVisibleRect(mScrollRect);
      }
      mCurrentStickyView.getLocationOnScreen(stickyViewP);
      ev.offsetLocation(0, stickyViewP[1] - mScrollRect.top);
    }
    return super.dispatchTouchEvent(ev);
  }

  @Override
  protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(canvas);
    if (mCurrentStickyView != null) {
      canvas.save();
      mCurrentStickyView.getLocationOnScreen(mStickyP);
      int realOffset = (mStickyOffset <= 0 ? mStickyOffset : 0);
      canvas.translate(mStickyP[0], getScrollY() + realOffset);
      canvas.clipRect(0, realOffset, mCurrentStickyView.getWidth(),
                      mCurrentStickyView.getHeight());
      mCurrentStickyView.draw(canvas);
      canvas.restore();
    }
  }

  @Override
  public boolean onTouchEvent(MotionEvent ev) {
    if(!scrollable) {
      return true; // when scrollable is set to false, then eat the touch event
    }
    if (mRedirectTouchToStickyView) {

      if (mScrollRect == null) {
        mScrollRect = new Rect();
        getGlobalVisibleRect(mScrollRect);
      }
      mCurrentStickyView.getLocationOnScreen(stickyViewP);
      ev.offsetLocation(0, -(stickyViewP[1] - mScrollRect.top));
    }

    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
      mHasNotDoneActionDown = false;
    }

    if (mHasNotDoneActionDown) {
      MotionEvent down = MotionEvent.obtain(ev);
      down.setAction(MotionEvent.ACTION_DOWN);
      mHasNotDoneActionDown = false;
      down.recycle();
    }

    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
      ox = ev.getX();
      oy = ev.getY();
      // Dispatch touch event to parent view
      startNestedScroll(ViewCompat.SCROLL_AXIS_HORIZONTAL | ViewCompat.SCROLL_AXIS_VERTICAL);
    }

    if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) {
      mHasNotDoneActionDown = true;
      // stop nested scrolling dispatch
      stopNestedScroll();
    }

    if (ev.getAction() == MotionEvent.ACTION_MOVE) {
      float clampedX = ev.getX();
      float clampedY = ev.getY();
      int dx = (int) (ox - clampedX);
      int dy = (int) (oy - clampedY);

      if (dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)) {
        // sub dx/dy was consumed by parent view!!!
        ev.setLocation(clampedX+consumed[0],clampedY+consumed[1]);
      }
      ox = ev.getX();
      oy = ev.getY();
    }

    boolean result = super.onTouchEvent(ev);
    if (wxGesture != null) {
      result |= wxGesture.onTouch(this, ev);
    }
    return result;
  }

  @Override
  public void setNestedScrollingEnabled(boolean enabled) {
    childHelper.setNestedScrollingEnabled(enabled);
  }

  @Override
  public boolean isNestedScrollingEnabled() {
    return childHelper.isNestedScrollingEnabled();
  }

  @Override
  public boolean startNestedScroll(int axes) {
    return childHelper.startNestedScroll(axes);
  }

  @Override
  public void stopNestedScroll() {
    childHelper.stopNestedScroll();
  }

  @Override
  public boolean hasNestedScrollingParent() {
    return childHelper.hasNestedScrollingParent();
  }

  public boolean isScrollable() {
    return scrollable;
  }

  public void setScrollable(boolean scrollable) {
    this.scrollable = scrollable;
  }

  @Override
  public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
    return childHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);
  }

  @Override
  public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
    return childHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
  }

  @Override
  public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
    return childHelper.dispatchNestedFling(velocityX, velocityY, consumed);
  }

  @Override
  public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
    return childHelper.dispatchNestedPreFling(velocityX, velocityY);
  }

  @Override
  public boolean onNestedPreFling(View target, float velocityX,
                                  float velocityY) {
    return dispatchNestedPreFling(velocityX, velocityY);
  }

  @Override
  public boolean onNestedFling(View target, float velocityX, float velocityY,
                               boolean consumed) {
    return dispatchNestedFling(velocityX, velocityY, consumed);
  }

  @Override
  public void fling(int velocityY) {
    super.fling(velocityY);
    if (mScrollerTask != null) {
      mScrollerTask.removeMessages(0);
    }
    startScrollerTask();
  }

  @Override
  protected void onScrollChanged(int x, int y, int oldx, int oldy) {
    mScrollX = getScrollX();
    mScrollY = getScrollY();
    onScroll(WXScrollView.this, mScrollX, mScrollY);
    View view = getChildAt(getChildCount() - 1);
    if (view == null) {
      return;
    }
    int d = view.getBottom();
    d -= (getHeight() + mScrollY);
    if (d == 0) {
      onScrollToBottom(mScrollX, mScrollY);
    }
    int count = mScrollViewListeners == null ? 0 : mScrollViewListeners.size();
    for (int i = 0; i < count; ++i) {
      mScrollViewListeners.get(i).onScrollChanged(this, x, y, oldx, oldy);
    }

    showStickyView();
  }

  protected void onScroll(WXScrollView scrollView, int x, int y) {
    int count = mScrollViewListeners == null ? 0 : mScrollViewListeners.size();
    for (int i = 0; i < count; ++i) {
      mScrollViewListeners.get(i).onScroll(this, x, y);
    }
  }

  protected void onScrollToBottom(int x, int y) {
    int count = mScrollViewListeners == null ? 0 : mScrollViewListeners.size();
    for (int i = 0; i < count; ++i) {
      mScrollViewListeners.get(i).onScrollToBottom(this, x, y);
    }
  }

  private void showStickyView() {
    if(mWAScroller == null){
      return;
    }
    View curStickyView = procSticky(mWAScroller.getStickMap());

    if (curStickyView != null) {
      mCurrentStickyView = curStickyView;
    } else {
      mCurrentStickyView = null;
    }
  }

  private View procSticky(Map<String, Map<String, WXComponent>> mStickyMap) {
    if (mStickyMap == null) {
      return null;
    }
    Map<String, WXComponent> stickyMap = mStickyMap.get(mWAScroller.getRef());
    if (stickyMap == null) {
      return null;
    }

    Iterator<Entry<String, WXComponent>> iterator = stickyMap.entrySet().iterator();
    Entry<String, WXComponent> entry = null;
    WXComponent stickyData;
    while (iterator.hasNext()) {
      entry = iterator.next();
      stickyData = entry.getValue();

      getLocationOnScreen(stickyScrollerP);
      stickyData.getHostView().getLocationOnScreen(stickyViewP);
      int parentH = 0;
      if(stickyData.getParent()!=null && stickyData.getParent().getRealView()!=null){
        parentH=stickyData.getParent().getRealView().getHeight();
      }
      int stickyViewH = stickyData.getHostView().getHeight();
      int stickyShowPos = stickyScrollerP[1];
      int stickyStartHidePos = -parentH + stickyScrollerP[1] + stickyViewH;
      if (stickyViewP[1] <= stickyShowPos && stickyViewP[1] >= (stickyStartHidePos - stickyViewH)) {
        mStickyOffset = stickyViewP[1] - stickyStartHidePos;
        stickyData.setStickyOffset(stickyViewP[1]-stickyScrollerP[1]);
        return stickyData.getHostView();
      }else{
        stickyData.setStickyOffset(0);
      }
    }
    return null;
  }

  @Override
  public boolean handleMessage(Message msg) {
    switch (msg.what) {
      case 0:
        if (mScrollerTask != null) {
          mScrollerTask.removeMessages(0);
        }
        int newPosition = getScrollY();
        if (mInitialPosition - newPosition == 0) {//has stopped
          onScrollStopped(WXScrollView.this, getScrollX(), getScrollY());
        } else {
          onScroll(WXScrollView.this, getScrollX(), getScrollY());
          mInitialPosition = getScrollY();
          if (mScrollerTask != null) {
            mScrollerTask.sendEmptyMessageDelayed(0, mCheckTime);
          }
        }
        break;
      default:
        break;
    }
    return true;
  }

  protected void onScrollStopped(WXScrollView scrollView, int x, int y) {
    int count = mScrollViewListeners == null ? 0 : mScrollViewListeners.size();
    for (int i = 0; i < count; ++i) {
      mScrollViewListeners.get(i).onScrollStopped(this, x, y);
    }
  }

  @Override
  public void destroy() {
    if (mScrollerTask != null) {
      mScrollerTask.removeCallbacksAndMessages(null);
    }
  }

  @Override
  public void registerGestureListener(WXGesture wxGesture) {
    this.wxGesture = wxGesture;
  }

  public Rect getContentFrame() {
    return new Rect(0, 0, computeHorizontalScrollRange(), computeVerticalScrollRange());
  }

  public interface WXScrollViewListener {

    void onScrollChanged(WXScrollView scrollView, int x, int y, int oldx, int oldy);

    void onScrollToBottom(WXScrollView scrollView, int x, int y);

    void onScrollStopped(WXScrollView scrollView, int x, int y);

    void onScroll(WXScrollView scrollView, int x, int y);
  }

  public void setWAScroller(WXScroller mWAScroller) {
    this.mWAScroller = mWAScroller;
  }
}
