/*
 * 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);
    }
    boolean result = super.dispatchTouchEvent(ev);
    if (wxGesture != null) {
      result |= wxGesture.onTouch(this, ev);
    }
    return result;
  }

  @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();
    }

    return super.onTouchEvent(ev);
  }

  @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;
  }
}
