package nz.org.winters.legodisplaysequencer.storage;

import android.annotation.SuppressLint;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.TextView;

import com.bignerdranch.android.multiselector.SingleSelector;
import com.bignerdranch.android.multiselector.SwappingHolder;

import nz.org.winters.legodisplaysequencer.R;
import nz.org.winters.legodisplaysequencer.sequence.Sequence;
import nz.org.winters.legodisplaysequencer.sequence.SequenceItem;
import nz.org.winters.legodisplaysequencer.views.helper.ItemTouchHelperAdapter;
import nz.org.winters.legodisplaysequencer.views.helper.OnStartDragListener;

/**
 * @author MWinters
 */
public class SequenceItemsFirebaseRecyclerIndexAdapter extends RecyclerView.Adapter<SequenceItemsFirebaseRecyclerIndexAdapter.SequenceItemViewHolder>
    implements ItemTouchHelperAdapter
{
  private static final String TAG = SequenceItemsFirebaseRecyclerIndexAdapter.class.getSimpleName();
  private final Callbacks callbacks;
  private final OnStartDragListener dragStartListener;
  private Sequence sequence;
  private boolean enabled = true;

  SequenceItemsFirebaseRecyclerIndexAdapter(@NonNull Callbacks callbacks, @NonNull OnStartDragListener onStartDragListener) {
    super();
    this.sequence = null;
    this.dragStartListener = onStartDragListener;
    this.callbacks = callbacks;
    setHasStableIds(true);
  }

  public void setSequence(@Nullable Sequence sequence){
    this.sequence = sequence;
    notifyDataSetChanged();
  }

  @Override
  public void onItemDismiss(final int position) {
    Log.d(TAG, "Position " + position);
    this.sequence.removeItem(position);
    notifyItemRemoved(position);
  }

  @Override
  public void onItemMoveFinished() {
    this.sequence.itemMoveFinished();
  }


  @Override
  public boolean onItemMove(int fromPosition, int toPosition) {
    Log.d(TAG, "From " + fromPosition + " To " + toPosition);
    sequence.moveItem(fromPosition, toPosition);
    notifyItemMoved(fromPosition, toPosition);
    callbacks.getSequenceItemSelector().tapSelection(toPosition,0);
    return true;
  }

  @Override
  public int getItemViewType(int position) {
    SequenceItem item = getItem(position);
    return item == null ? 0 : item.getViewType();
  }

  @Nullable
  private SequenceItem getItem(int position) {
    return sequence == null ? null : sequence.getItem(position);
  }


  @Override
  public long getItemId(int position) {
    SequenceItem item = getItem(position);
    return item == null ? -1 : item.getSequenceOrder();
  }

  @Override
  public int getItemCount() {
    return sequence == null ? 0 : sequence.getItemsSize();
  }

  @Override
  public SequenceItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view;
    switch (viewType) {
      case SequenceItem.SEQUENCE_VIEW_TYPE_DELAY:
        view =  LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_sequence_delay, parent, false);
        break;
      case SequenceItem.SEQUENCE_VIEW_TYPE_TRACK_POINT:
        view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_sequence_track_point, parent, false);
        break;
      case SequenceItem.SEQUENCE_VIEW_TYPE_TRAIN_DRIVE:
        view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_sequence_drive_train, parent, false);
        break;
      case SequenceItem.SEQUENCE_VIEW_TYPE_PWM_VALUE:
        view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_sequence_pwm_value, parent, false);
        break;
      case SequenceItem.SEQUENCE_VIEW_TYPE_TRAIN_SPEED:
        view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_sequence_train_speed, parent, false);
        break;
      case SequenceItem.SEQUENCE_VIEW_TYPE_COLOUR_WAIT:
        view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_sequence_wait_colour, parent, false);
        break;
      case SequenceItem.SEQUENCE_VIEW_TYPE_SBRICK:
        view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_sequence_sbrick, parent, false);
        break;
      case SequenceItem.SEQUENCE_VIEW_TYPE_LED_POWER:
        view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_sequence_led_power, parent, false);
        break;
      case SequenceItem.SEQUENCE_VIEW_TYPE_DELAY_MILLISECONDS:
        view =  LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_sequence_delay_milliseconds, parent, false);
        break;
      default:

        view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);
        break;
    }
    view.setEnabled(isEnabled());
    return new SequenceItemViewHolder(view, callbacks,this);
  }

  @SuppressLint("ClickableViewAccessibility")
  @Override
  public void onBindViewHolder(final SequenceItemViewHolder sequenceItemViewHolder, int position) {
    SequenceItem model = getItem(position);
    if(model != null) {
      sequenceItemViewHolder.bind(model, (v, event) -> {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
          dragStartListener.onStartDrag(sequenceItemViewHolder);
        }
        return false;
      });
    }
  }

  public void setEnabled(boolean enable) {
    this.enabled = enable;
    notifyItemRangeChanged(0,sequence.getItemsSize());
  }

  public boolean isEnabled() {
    return enabled;
  }

  public interface Callbacks {
    void tapSelection(@NonNull SequenceItemViewHolder viewHolder);


    @NonNull
    SingleSelector getSequenceItemSelector();

    @NonNull
    Sequence getSelectedSequence();

    void notifyItemChanged(int adapterPosition);

    @NonNull
    FragmentManager getFragmentManager();

    @NonNull
    Context getContext();

    void runSingleSequenceItem(@NonNull SequenceItem model);

    boolean isEnabled();
  }


  public static class SequenceItemViewHolder extends SwappingHolder implements View.OnClickListener, SequenceItem.OnValueChanged {
    private final ImageButton editButton;
    private final ImageButton playButton;
    private final View moveHandleView;
    private final TextView textView;
    private final Callbacks callbacks;
    private final RecyclerView.Adapter adapter;
    private SequenceItem model;

    SequenceItemViewHolder(@NonNull View itemView, @NonNull Callbacks callbacks, @NonNull RecyclerView.Adapter adapter) {
      super(itemView, callbacks.getSequenceItemSelector());
      this.callbacks = callbacks;
      this.adapter = adapter;
      itemView.setOnClickListener(this);
      textView = itemView.findViewById(android.R.id.text1);
      editButton = itemView.findViewById(R.id.buttonEdit);
      editButton.setOnClickListener(this);
      playButton = itemView.findViewById(R.id.buttonPlay);
      playButton.setOnClickListener(this);
      moveHandleView = itemView.findViewById(R.id.imageType);

    }

    void bind(@NonNull SequenceItem model, @NonNull View.OnTouchListener onTouchListener) {
      this.model = model;
      textView.setText(model.getDisplayString(callbacks.getContext()));
      model.setOnValueChanged(this);
      moveHandleView.setOnTouchListener(onTouchListener);
      moveHandleView.setEnabled(callbacks.isEnabled());
      editButton.setEnabled(callbacks.isEnabled());
      playButton.setEnabled(callbacks.isEnabled());
    }

    @Override
    public void onClick(View view) {
      if (view == editButton) {
        model.showEditor(callbacks.getContext(), callbacks.getFragmentManager(), callbacks.getSelectedSequence(), adapter);
      }else if (view == playButton) {
        callbacks.runSingleSequenceItem(model);
      } else {
        callbacks.tapSelection(this);
      }
    }

    @Override
    public void valueChanged(@NonNull SequenceItem sequenceItem) {
      callbacks.notifyItemChanged(this.getAdapterPosition());
    }
  }
}
