package de.sebse.fuplanner.fragments.moddetails;

import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.ms.square.android.expandabletextview.ExpandableTextView;

import java.util.ArrayList;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.types.Announcement;
import de.sebse.fuplanner.services.KVV.types.Assignment;
import de.sebse.fuplanner.services.KVV.types.Event;
import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.UtilsDate;
import de.sebse.fuplanner.tools.logging.Logger;
import de.sebse.fuplanner.tools.ui.CustomViewHolder;
import de.sebse.fuplanner.tools.ui.ItemViewHolder;
import de.sebse.fuplanner.tools.ui.StringViewHolder;

class ModDetailOverviewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private static final int MAX_ITEMS_PER_PREVIEW = 2;

    private static final int TYPE_HEADER = 0;
    private static final int TYPE_DESCRIPTION = 1;
    private static final int TYPE_ITEM = 2;
    private static final int TYPE_SHOW_MORE = 3;

    @Nullable private final ModDetailListener mListener;

    private Modules.Module mValue;
    private final ArrayList<Pair<Integer, Object>> mPositionalData;
    private Logger log = new Logger(this);

    ModDetailOverviewAdapter(@Nullable final ModDetailListener listener) {
        mValue = null;
        mPositionalData = new ArrayList<>();
        mListener = listener;
    }

    public void setModule(Modules.Module module) {
        mValue = module;
        this.setModule();
    }

    public void setModule() {
        mPositionalData.clear();
        mPositionalData.add(new Pair<>(TYPE_HEADER, ModulePart.DESCRIPTION));
        mPositionalData.add(new Pair<>(TYPE_DESCRIPTION, null));
        mPositionalData.add(new Pair<>(TYPE_HEADER, ModulePart.ANNOUNCEMENT));
        addPositionalListData(getAnnounceCount(), ModulePart.ANNOUNCEMENT);
        mPositionalData.add(new Pair<>(TYPE_HEADER, ModulePart.ASSIGNMENT));
        addPositionalListData(getAssignmentCount(), ModulePart.ASSIGNMENT);
        mPositionalData.add(new Pair<>(TYPE_HEADER, ModulePart.EVENT));
        addPositionalListData(getEventsCount(), ModulePart.EVENT);
        this.notifyDataSetChanged();
    }

    private void addPositionalListData(int count, int category) {
        for (int i = 0; i < Math.min(MAX_ITEMS_PER_PREVIEW, count); i++) {
            mPositionalData.add(new Pair<>(TYPE_ITEM, category+1024*i));
        }
        if (count > MAX_ITEMS_PER_PREVIEW)
            mPositionalData.add(new Pair<>(TYPE_SHOW_MORE, category));
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view;
        switch (viewType) {
            case TYPE_HEADER:
                view = LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.list_all_caption, parent, false);
                return new StringViewHolder(view);
            case TYPE_DESCRIPTION:
                view = LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.list_moddetails_description, parent, false);
                return new DescriptionViewHolder(view);
            case TYPE_ITEM:
                view = LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.list_all_items, parent, false);
                return new ItemViewHolder(view);
            case TYPE_SHOW_MORE:
                view = LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.list_all_show_more, parent, false);
                return new CustomViewHolder(view);
            default:
                //noinspection ConstantConditions
                return null;
        }
    }

    @Override
    public int getItemViewType(int position) {
        // Note that unlike in ListView adapters, types don't have to be contiguous
        if (position < mPositionalData.size())
            return mPositionalData.get(position).first;
        else return -1;
    }

    @Override
    public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
        if (mValue == null || position > mPositionalData.size())
            return;
        Pair<Integer, Object> data = mPositionalData.get(position);
        switch (data.first) {
            case TYPE_HEADER:
                StringViewHolder h = (StringViewHolder) holder;
                switch ((Integer) data.second) {
                    case ModulePart.DESCRIPTION:
                        h.mString.setText(R.string.description);
                        break;
                    case ModulePart.ANNOUNCEMENT:
                        h.mString.setText(h.mView.getResources().getString(R.string.announcements_count, getAnnounceCount()));
                        break;
                    case ModulePart.ASSIGNMENT:
                        h.mString.setText(h.mView.getResources().getString(R.string.assignments_count, getAssignmentCount()));
                        break;
                    case ModulePart.EVENT:
                        h.mString.setText(h.mView.getResources().getString(R.string.upcoming_events_count, getEventsCount()));
                        break;
                }
                break;
            case TYPE_DESCRIPTION:
                DescriptionViewHolder d = (DescriptionViewHolder) holder;
                d.mText.setText(mValue.description);
                break;
            case TYPE_ITEM:
                int section = ((Integer) data.second) % 1024;
                int index = ((Integer) data.second) / 1024;
                ItemViewHolder i = (ItemViewHolder) holder;
                switch (section) {
                    case ModulePart.ANNOUNCEMENT:
                        if (mValue.announcements == null) throw new AssertionError();
                        Announcement announce = mValue.announcements.get(index);
                        i.mTitle.setText(announce.getTitle());
                        i.mSubLeft.setText(announce.getCreatedBy());
                        i.mSubRight.setText(UtilsDate.getModifiedDateTime(i.mView.getContext(), announce.getCreatedOn()));
                        i.mView.setOnClickListener(view -> {
                            if (mListener != null) mListener.gotoFragmentPart(section, index);
                        });
                        break;
                    case ModulePart.ASSIGNMENT:
                        if (mValue.assignments == null) throw new AssertionError();
                        Assignment assignment = mValue.assignments.get(index);
                        i.mTitle.setText(assignment.getTitle());
                        if(assignment.isOpen())
                            i.mSubLeft.setText(i.mView.getResources().getText(R.string.open));
                        else
                            i.mSubLeft.setText(i.mView.getResources().getText(R.string.closed));
                        i.mSubRight.setText(UtilsDate.getModifiedDateTime(i.mView.getContext(), assignment.getDueDate()));
                        i.mView.setOnClickListener(view -> {
                            if (mListener != null) mListener.gotoFragmentPart(section, index);
                        });
                        break;
                    case ModulePart.EVENT:
                        if (mValue.events == null) throw new AssertionError();
                        Event event = mValue.events.getUpcoming(index);
                        i.mTitle.setText(event.getTitle());
                        i.mSubLeft.setText(event.getType());
                        String start, end;
                        if (UtilsDate.dateEquals(event.getStartDate(), System.currentTimeMillis()))
                            start = UtilsDate.getModifiedTime(i.mView.getContext(), event.getStartDate());
                        else
                            start = UtilsDate.getModifiedDateTime(i.mView.getContext(), event.getStartDate());
                        if (UtilsDate.dateEquals(event.getStartDate(), event.getEndDate()))
                            end = UtilsDate.getModifiedTime(i.mView.getContext(), event.getEndDate());
                        else
                            end = UtilsDate.getModifiedDateTime(i.mView.getContext(), event.getEndDate());
                        i.mSubRight.setText(i.mView.getResources().getString(R.string.date_scale,
                                start, end
                                ));
                        i.mView.setOnClickListener(view -> {
                            if (mListener != null) mListener.gotoFragmentPart(section, index);
                        });
                        break;
                }
                break;
            case TYPE_SHOW_MORE:
                CustomViewHolder c = (CustomViewHolder) holder;
                c.mView.setOnClickListener(view -> {
                    if (mListener != null) mListener.gotoFragmentPart((Integer) data.second, -1);
                });
                break;
        }
    }

    @Override
    public int getItemCount() {
        return mPositionalData.size();
    }

    private int getAnnounceCount() {
        if (mValue.announcements != null)
            return mValue.announcements.size();
        return 0;
    }

    private int getAssignmentCount() {
        if (mValue.assignments != null)
            return mValue.assignments.size();
        return 0;
    }

    private int getEventsCount() {
        if (mValue.events != null)
            return mValue.events.sizeUpcoming();
        return 0;
    }










    class DescriptionViewHolder extends CustomViewHolder {
        final ExpandableTextView mText;

        DescriptionViewHolder(View view) {
            super(view);
            mText = view.findViewById(R.id.expand_text_view);//.findViewById(R.id.description);
        }

        @Override
        public String toString() {
            return super.toString() + " '" + mText.getText() + "'";
        }
    }


}
