content: /*
   * Copyright 2016 J. Alexandre Oliveira
   *
   * 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.alexive.graphicalutils.lists;
  
  import android.content.Context;
  import android.graphics.Rect;
  import android.support.v7.widget.GridLayoutManager;
  import android.support.v7.widget.RecyclerView;
  import android.view.Gravity;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.FrameLayout;
  import android.widget.ImageButton;
  import android.widget.ImageView;
  import android.widget.LinearLayout;
  import android.widget.TextView;
  
  import com.alexive.graphicalutils.R;
  import com.alexive.graphicalutils.view.ProportionalImageView;
  import com.alexive.graphicalutils.view.ViewUtils;
  
  /**
   * Base grid adapter class. Provides subheaders, click listeners setting, etc.
   */
  public abstract class GridAdapter extends ListAdapter {
      /*
      ---------------------
      * ---------------------
      * TODO MAJOR REFACTOR!!!!!!! or just make it an hybrid (rows with n columns or w/ 1)
      * ---------------------
      * ---------------------
       */
  
      private final DetailsType mDetailsViewType;
      private final String DETAILS_VIEW_TAG = "detailsviewtag";
      private GridItemSpecs gridSpecs;
      private int numCols;
  
      public GridAdapter(DetailsType type) {
          super();
          mDetailsViewType = type;
      }
  
      @Override
      public AwesomeViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
          if (i == ListItemType.GRID_ITEM.resId) {
              return getItemView(viewGroup);
          } else
              return super.onCreateViewHolder(viewGroup, i);
      }
  
      protected AwesomeViewHolder getItemView(ViewGroup group) {
          if (gridSpecs == null)
              gridSpecs = new GridItemSpecs();
          LayoutInflater inflater = LayoutInflater.from(group.getContext());
          View base = inflater.inflate(gridSpecs.detailsViewFloats ? R.layout
                  .grid_float_headerfooter_tile : R.layout.grid_dummy_tile, group, false);
          base.setClickable(true);
          AwesomeViewHolder result = new AwesomeViewHolder(base);
          setListenerForHolder(result);
  
          ProportionalImageView imageView = (ProportionalImageView) base.findViewById(R.id.imageView);
          if (gridSpecs.forceSquareImage)
              imageView.setSquare();
          result.setImageView1(imageView);
          if (mDetailsViewType == DetailsType.NONE) {
              return result;
          }
          View details = getDetailsView(inflater, group, result);
  
          ImageButton imageButton = (ImageButton) details.findViewById(R.id.imageButton);
          imageButton.setOnClickListener(new ButtonListener(result));
          result.setButton(imageButton);
  
          if (gridSpecs.detailsViewFloats) {
              //We just add it to the framelayout and set the gravity
              FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams
                      .FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
              FrameLayout fl = (FrameLayout) base.findViewById(R.id.floatParent);
              params.gravity = gridSpecs.detailsGravityIsTop ? Gravity.TOP : Gravity.BOTTOM;
              fl.addView(details, 1, params);
          } else {
              LinearLayout parent = (LinearLayout) base.findViewById(R.id.noFloatParent);
  //            LinearLayout parent = (LinearLayout) base.findViewById(gridSpecs.detailsGravityIsTop ? R
  //                    .id.headerNoFloat : R.id.footerNoFloat);
  //            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams
  //                    .FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
              parent.addView(details, gridSpecs.detailsGravityIsTop ? 0 : 1);
              base.findViewById(R.id.noFloatParent).requestLayout();
          }
  
          return result;
      }
  
  //    public String getGridImageTransitionName(Context c) {
  //        return c.getString(R.string.image_transition_name);
  //    }
  
      public View getDetailsView(LayoutInflater inflater, ViewGroup parent,
                                 AwesomeViewHolder result) {
          //TODO FORCE DARK MODE
          View view = null;
          switch (mDetailsViewType) {
              case SINGLE_LINE:
                  view = inflater.inflate(R.layout.griddetails_single_line, null);
                  break;
              case TWO_LINES:
                  view = inflater.inflate(R.layout.griddetails_two_lines, null);
                  break;
              default:
              case NONE:
                  return null;
          }
          view.setTag(DETAILS_VIEW_TAG);
          result.setDetailsView(view);
          result.setText1((TextView) view.findViewById(android.R.id.text1));
          result.setText2((TextView) view.findViewById(android.R.id.text2));
          result.setButton((ImageButton) view.findViewById(R.id.imageButton));
          return view;
      }
  
      @Override
      public boolean shouldSubHeaderTextColorBeAccent() {
          return false;
      }
  
      @Override
      public boolean drawDivider(int i) {
          //Dividers in a grid make no sense.
          return false;
      }
  
      @Override
      public void bindDataToListItem(int index,
                                     View itemView,
                                     ImageView iconOrAvatar,
                                     ImageButton button,
                                     TextView... texts) {
          //useless
          //you should override bindDataToItem
      }
  
      @Override
      protected void preBindData(int i, AwesomeViewHolder awesomeViewHolder) {
          bindDataToItem(i,
                  awesomeViewHolder.itemView,
                  awesomeViewHolder.getDetailsView(),
                  awesomeViewHolder.getImageView1(),
                  awesomeViewHolder.button,
                  awesomeViewHolder.text1,
                  awesomeViewHolder.text2);
      }
  
      /**
       * Fills in the list item
       *
       * @param index        The index of the item
       * @param itemView     The list item's view
       * @param detailsView  Item's detail view, typically under the image
       * @param imageViewOrAvatar    The item's ImageView, or the avatar if it's an ordinary item
       * @param imageButton  If it's an ordinary list item, it's button
       * @param txt          The item's text views, from top to bottom, left to right
       */
      public abstract void bindDataToItem(int index,
                                          View itemView,
                                          View detailsView,
                                          ImageView imageViewOrAvatar,
                                          ImageButton imageButton,
                                          TextView... txt);
  
  
      public void setItemSpecs(GridItemSpecs specs) {
          gridSpecs = specs;
      }
  
      //public abstract void bindDataToItemView(int position, ImageView imageView, View... detailsView);
  
      public GridLayoutManager getGridLayoutManager(Context ctx, int numColumns) {
          this.numCols = numColumns;
          GridLayoutManager mngr = new GridLayoutManager(ctx, numColumns);
          mngr.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
              @Override
              public int getSpanSize(int position) {
                  return getItemViewType(position) == ListItemType.GRID_ITEM.resId ? 1 : numCols;
              }
          });
          return mngr;
      }
  
      public RecyclerView.ItemDecoration getDecorationForSmallSpacing(Context c) {
          return new Decorator(ViewUtils.convertDPtoPixels(c, 1));
      }
  
      public RecyclerView.ItemDecoration getDecorationForLargeSpacing(Context c) {
          return new Decorator(ViewUtils.convertDPtoPixels(c, 4));
      }
  
      public enum DetailsType {
          NONE,
          SINGLE_LINE,
          TWO_LINES
      }
  
      public static class GridItemSpecs {
          public boolean detailsGravityIsTop = false;
          public boolean detailsViewFloats = false;
          public boolean forceDarkMode = false;
          public boolean forceSquareImage = true;
      }
  
      private class Decorator extends RecyclerView.ItemDecoration {
  
          private final int padding;
  
          public Decorator(int padding) {
              this.padding = padding;
          }
  
          @Override
          public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
              super.getItemOffsets(outRect, view, parent, state);
              int pos = parent.getChildAdapterPosition(view);
              if (getListItemDataType(pos) == ListItemType.SUB_HEADER)
                  return;
              //TODO Faster approach
              //TODO actually compute the list item's padding IF it's on the edge.
              //Having subheaders/items taking up a full row made the code I had before messed up
  //      //If the list has subheaders, without this the padding will be VERY EFFED Up.
  //      int newPos = 0;
  //      for (int i = 0; i <= pos; i++) {
  //        if (isSubHeader(i)) {
  //         newPos = 0;
  //        }else
  //          newPos++;
  //      }
  //
  //      if(newPos % numCols != 0)
              outRect.left = padding;
  //      if ((newPos + 1) % numCols != 0);
              outRect.right = padding;
              outRect.bottom = padding;
              outRect.top = padding;
          }
      }
  }
  