content: /**
   * 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 org.apache.weex.ui.component.list.template;
  
  import android.support.v4.util.ArrayMap;
  import android.support.v7.widget.LinearLayoutManager;
  import android.support.v7.widget.RecyclerView;
  import android.support.v7.widget.StaggeredGridLayoutManager;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.FrameLayout;
  
  import org.apache.weex.common.Constants;
  import org.apache.weex.ui.view.refresh.wrapper.BounceRecyclerView;
  
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * StickyHelper For Template List
   * Created by furture on 2017/8/24.
   */
  public class TemplateStickyHelper {
      private WXRecyclerTemplateList recyclerTemplateList;
      private List<Integer> stickyPositions;
      private ArrayMap<Integer, TemplateViewHolder>   stickyHolderCache;
      private List<String> mStickyTypes;
  
  
      public TemplateStickyHelper(WXRecyclerTemplateList recyclerTemplateList) {
          this.recyclerTemplateList = recyclerTemplateList;
          this.stickyPositions = new ArrayList<>();
          this.stickyHolderCache = new ArrayMap();
          this.mStickyTypes = new ArrayList<>(8);
      }
  
      /**
       * dispatch scroll event, sticky  header
       * */
      public void onBeforeScroll(int dx, int dy) {
          if(stickyPositions == null || stickyPositions.size() == 0){
             return;
          }
          BounceRecyclerView bounceRecyclerView = recyclerTemplateList.getHostView();
          RecyclerView recyclerView = recyclerTemplateList.getHostView().getInnerView();
          RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
          int firstVisiblePosition = -1;
          int lastVisiblePosition = -1;
          if (layoutManager instanceof LinearLayoutManager) {
              firstVisiblePosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
              lastVisiblePosition  = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
          }else if (layoutManager instanceof StaggeredGridLayoutManager) {
              int [] firstVisibleItemPositions = new int[3];//max 3 column
              firstVisiblePosition = ((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(firstVisibleItemPositions)[0];
              lastVisiblePosition = ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(firstVisibleItemPositions)[0];
          }
          if(firstVisiblePosition < 0){
              return;
          }
  
          TemplateViewHolder firstVisibleItemHolder = (TemplateViewHolder) recyclerView.findViewHolderForAdapterPosition(firstVisiblePosition);
          if(firstVisibleItemHolder == null){
              return;
          }
  
          //find match sticky position
          int matchStickyPosition = -1;
          for (Integer headerPosition : stickyPositions){
              if(headerPosition == null){
                  continue;
              }
              if(headerPosition <= firstVisiblePosition){
                  matchStickyPosition = Math.max(matchStickyPosition, headerPosition);
              }else{
                  break;
              }
          }
          if(matchStickyPosition < 0){
              //remove holder for match position not found
              View stickyFakeView = bounceRecyclerView.getChildAt(bounceRecyclerView.getChildCount() - 1);
              if(stickyFakeView.getTag() instanceof TemplateViewHolder){
                  TemplateViewHolder stickyFakeViewHolder = (TemplateViewHolder) stickyFakeView.getTag();
                  bounceRecyclerView.removeView(stickyFakeViewHolder.itemView);
                  stickyFakeViewHolder.itemView.setTranslationY(0);
                  if(stickyFakeViewHolder.getComponent() != null
                          && stickyFakeViewHolder.getComponent().getEvents().contains(Constants.Event.UNSTICKY)){
                      stickyFakeViewHolder.getComponent().fireEvent(Constants.Event.UNSTICKY);
                  }
              }
  
              /**check has sticky cell not visible */
              for(int i=0; i<recyclerView.getChildCount(); i++) {
                  View itemView = recyclerView.getChildAt(i);
                  TemplateViewHolder itemHolder = (TemplateViewHolder) recyclerView.getChildViewHolder(itemView);
                  if (itemHolder == null) {
                      continue;
                  }
                  int adapterPosition = itemHolder.getAdapterPosition();
                  if (!stickyPositions.contains(adapterPosition)) {
                      continue;
                  }
                  if(itemView.getVisibility() != View.VISIBLE) {
                      itemView.setVisibility(View.VISIBLE);
                  }
              }
              return;
          }
  
          //onCreate holder for match position if not exist
          View stickyFakeView = bounceRecyclerView.getChildAt(bounceRecyclerView.getChildCount() - 1);
          if(!(stickyFakeView.getTag() instanceof TemplateViewHolder)
                  || ((TemplateViewHolder) stickyFakeView.getTag()).getHolderPosition() != matchStickyPosition){
  
               //remove previous sticky header
              if(stickyFakeView.getTag() instanceof TemplateViewHolder &&
                      ((TemplateViewHolder) stickyFakeView.getTag()).getHolderPosition() != matchStickyPosition){
                  TemplateViewHolder stickyFakeViewHolder = (TemplateViewHolder) stickyFakeView.getTag();
                  bounceRecyclerView.removeView(stickyFakeViewHolder.itemView);
                  stickyFakeViewHolder.itemView.setTranslationY(0);
                  if(stickyFakeViewHolder.getComponent() != null
                          && stickyFakeViewHolder.getComponent().getEvents().contains(Constants.Event.UNSTICKY)){
                      stickyFakeViewHolder.getComponent().fireEvent(Constants.Event.UNSTICKY);
                  }
              }
  
              //onCreate new sticky
              int stickyHolderType = recyclerTemplateList.getItemViewType(matchStickyPosition);
              TemplateViewHolder fakeStickyHolder = stickyHolderCache.get(stickyHolderType);
              if(fakeStickyHolder == null){
                  fakeStickyHolder = recyclerTemplateList.onCreateViewHolder(recyclerView, stickyHolderType);
                  stickyHolderCache.put(stickyHolderType, fakeStickyHolder);
              }
              recyclerTemplateList.onBindViewHolder(fakeStickyHolder, matchStickyPosition);
              fakeStickyHolder.itemView.setTranslationY(0);
              fakeStickyHolder.itemView.setTag(fakeStickyHolder);
              FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
              fakeStickyHolder.getComponent().clearPreLayout();
              if(fakeStickyHolder.itemView.getParent() != null){
                  ViewGroup parent = (ViewGroup) fakeStickyHolder.itemView.getParent();
                  parent.removeView(fakeStickyHolder.itemView);
              }
              bounceRecyclerView.addView(fakeStickyHolder.itemView, params);
              fakeStickyHolder.getComponent().setLayout(fakeStickyHolder.getComponent());
              stickyFakeView = fakeStickyHolder.itemView;
              if(fakeStickyHolder.getComponent() != null
                      && fakeStickyHolder.getComponent().getEvents().contains(Constants.Event.STICKY)){
                  fakeStickyHolder.getComponent().fireEvent(Constants.Event.STICKY);
              }
          }
          TemplateViewHolder stickyFakeViewHolder = (TemplateViewHolder) stickyFakeView.getTag();
          for(int i=0; i<recyclerView.getChildCount(); i++){
              View itemView = recyclerView.getChildAt(i);
              TemplateViewHolder itemHolder = (TemplateViewHolder) recyclerView.getChildViewHolder(itemView);
              if(itemHolder == null){
                  continue;
              }
              int adapterPosition = itemHolder.getAdapterPosition();
              if(!stickyPositions.contains(adapterPosition)){
                  continue;
              }
              if(adapterPosition == stickyFakeViewHolder.getHolderPosition()){
                  if(itemView.getVisibility() != View.INVISIBLE) {
                      itemView.setVisibility(View.INVISIBLE);
                  }
              }else{
                  if(itemView.getVisibility() != View.VISIBLE) {
                      itemView.setVisibility(View.VISIBLE);
                  }
              }
          }
  
          if(firstVisibleItemHolder.getComponent().isSticky()){
              if(firstVisibleItemHolder.itemView.getY() < 0){
                  if(firstVisibleItemHolder.itemView.getVisibility() != View.INVISIBLE) {
                      firstVisibleItemHolder.itemView.setVisibility(View.INVISIBLE);
                  }
                  if(stickyFakeView.getVisibility() != View.VISIBLE) {
                      stickyFakeView.setVisibility(View.VISIBLE);
                  }
                  stickyFakeView.bringToFront();
              }else{
                  if(firstVisibleItemHolder.itemView.getVisibility() != View.VISIBLE) {
                      firstVisibleItemHolder.itemView.setVisibility(View.VISIBLE);
                  }
                  if(stickyFakeView.getVisibility() != View.GONE) {
                      stickyFakeView.setVisibility(View.GONE);
                  }
              }
          }else{
              if(stickyFakeView.getVisibility() != View.VISIBLE){
                  stickyFakeView.setVisibility(View.VISIBLE);
              }
          }
  
          //handle sticky is related, find next sticky position on screen
          int nextVisiblePostion = firstVisiblePosition + 1;
          if(lastVisiblePosition > 0){
              for(int i=nextVisiblePostion; i<= lastVisiblePosition; i++){
                  if(stickyPositions.contains(i)){
                      nextVisiblePostion = i;
                      break;
                  }
              }
          }
          if(!stickyPositions.contains(nextVisiblePostion)){
              if(stickyFakeViewHolder.itemView.getTranslationY() < 0){
                  stickyFakeViewHolder.itemView.setTranslationY(0);
              }
              return;
          }
          TemplateViewHolder nextStickyHolder = (TemplateViewHolder) recyclerView.findViewHolderForAdapterPosition(nextVisiblePostion);
          if(nextStickyHolder == null
                  || nextStickyHolder.getComponent() == null){
              return;
          }
          int translationY = (int)(nextStickyHolder.itemView.getY() - stickyFakeViewHolder.itemView.getMeasuredHeight());
          if(translationY <= 0){
              stickyFakeViewHolder.itemView.setTranslationY(translationY);
          }else{
              stickyFakeViewHolder.itemView.setTranslationY(0);
          }
      }
  
      public List<Integer> getStickyPositions() {
          if(stickyPositions == null){
              stickyPositions = new ArrayList<>();
          }
          return stickyPositions;
      }
  
      public List<String> getStickyTypes() {
          return mStickyTypes;
      }
  }
  