package com.thomasdh.roosterpgplus.Data;
import android.content.Context;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import com.thomasdh.roosterpgplus.Adapters.AnimatedPagerAdapter;
import com.thomasdh.roosterpgplus.Adapters.MultipleUrenClickListener;
import com.thomasdh.roosterpgplus.Helpers.Converter;
import com.thomasdh.roosterpgplus.Helpers.HelperFunctions;
import com.thomasdh.roosterpgplus.Models.Lesuur;
import com.thomasdh.roosterpgplus.R;
import org.apache.commons.lang3.StringUtils;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import fj.data.Array;
import lombok.NonNull;
import lombok.Setter;
import lombok.experimental.Accessors;
@Accessors(chain = true)
public class RoosterBuilder extends AsyncTask<Void, Void, Void> {
@Setter private Context context;
private ViewPager viewPager;
@Setter private int showDag = Calendar.MONDAY;
@Setter private boolean showVervangenUren = true;
@Setter private long lastLoad = -1;
@Setter private int urenCount = -1;
@Setter private BuilderFunctions builderFunctions = (lesuur, lesView, inflater) -> {
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
TextView vakTextView = (TextView) lesView.findViewById(R.id.rooster_vak);
TextView leraarTextView = (TextView) lesView.findViewById(R.id.rooster_leraar);
TextView lokaalTextView = (TextView) lesView.findViewById(R.id.rooster_lokaal);
TextView tijdenTextView = (TextView) lesView.findViewById(R.id.rooster_tijden);
vakTextView.setText(lesuur.vak);
leraarTextView.setText(StringUtils.join(lesuur.leraren, " & "));
lokaalTextView.setText(lesuur.lokaal);
tijdenTextView.setText(format.format(lesuur.lesStart) + " - " + format.format(lesuur.lesEind));
return lesView;
};
@Setter private OnDagScrollListener onDagScrollListener = (scrollY, dag) -> {};
private Array<Lesuur> lessen;
private boolean weekView;
private Converter converter;
private AnimatedPagerAdapter adapter;
private ArrayList<View> dagViews = new ArrayList<>();
private LinearLayout weekLinearLayout = null;
//region Builder-things
public RoosterBuilder(@NonNull Context context) {
setContext(context);
}
public RoosterBuilder in(@NonNull ViewPager viewPager) {
this.viewPager = viewPager;
return this;
}
public void build(List<Lesuur> lessen) {
if(lessen == null) lessen = new ArrayList<>();
build(Array.iterableArray(lessen));
}
public void build(Array<Lesuur> lessen) {
this.lessen = lessen;
execute();
}
@Override
protected Void doInBackground(Void... unused) {
if(viewPager == null) throw new IllegalStateException("Geen ViewPager");
if(viewPager.getAdapter() == null) throw new IllegalArgumentException("Geen ViewPagerAdapter");
adapter = (AnimatedPagerAdapter) viewPager.getAdapter();
if(lessen == null || lessen.isEmpty()) {
return null;
}
if(urenCount == -1) {
urenCount = lessen.foldLeft((a, b) -> b.uur > a ? b.uur : a, 0);
}
ContextCompat.getDrawable(context, R.drawable.diagonal_stripes_optioneeluur).setAlpha(100);
converter = new Converter(context);
boolean isWide = context.getResources().getBoolean(R.bool.isWideWeekview);
boolean isHigh = context.getResources().getBoolean(R.bool.isHighWeekview);
weekView = (isWide || isHigh);
int week = lessen.get(0).week;
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
Calendar now = Calendar.getInstance();
if (now.get(Calendar.WEEK_OF_YEAR) > 30 && week <= 30) { // Najaar en wil voorjaar, volgend jaar
calendar.set(Calendar.YEAR, now.get(Calendar.YEAR) + 1);
} else if (now.get(Calendar.WEEK_OF_YEAR) <= 30 && week > 30) { // Voorjaar en wil najaar, vorig jaar
calendar.set(Calendar.YEAR, now.get(Calendar.YEAR) - 1);
} else {
calendar.set(Calendar.YEAR, now.get(Calendar.YEAR));
}
calendar.set(Calendar.WEEK_OF_YEAR, week);
if(weekView) {
weekLinearLayout = new LinearLayout(context);
weekLinearLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0f));
int padding = converter.DPtoPX(10);
weekLinearLayout.setPadding(padding, 0, padding, 0);
}
for(int i = 2; i < 7; i++) {
int dag = i;
View dagView = LayoutInflater.from(context).inflate(R.layout.rooster_dag, null);
dagView = new DagBuilder()
.setParentView(dagView)
.setDag(dag)
.setLessen(lessen.filter(s -> s.dag == dag - 1))
.setDateViewCalendar(calendar)
.build();
if(weekView) {
weekLinearLayout.addView(dagView);
} else {
dagViews.add(dagView);
}
}
return null;
}
@Override
protected void onPostExecute(Void s) {
if(lessen == null || lessen.isEmpty()) {
View noRoosterView = LayoutInflater.from(context).inflate(R.layout.rooster_null, null);
adapter.setView(noRoosterView, 0, context);
viewPager.getAdapter().notifyDataSetChanged();
return;
}
boolean isWide = context.getResources().getBoolean(R.bool.isWideWeekview);
boolean isHigh = context.getResources().getBoolean(R.bool.isHighWeekview);
boolean weekViewNoScroll = isWide && isHigh;
if (weekView) {
LinearLayout container = new LinearLayout(context);
container.setOrientation(LinearLayout.VERTICAL);
container.addView(weekLinearLayout);
TextView lastUpdateTextView = getUpdateText(lastLoad);
lastUpdateTextView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
int pxPadding = converter.DPtoPX(10);
lastUpdateTextView.setPadding(pxPadding, pxPadding, pxPadding, pxPadding);
container.addView(lastUpdateTextView);
if (weekViewNoScroll || isWide) {
ScrollView scrollView = new ScrollView(context);
scrollView.addView(container);
scrollView.getViewTreeObserver().addOnScrollChangedListener(() -> {
int scrollY = scrollView.getScrollY();
for(int i = 0; i < 10; i++) {
onDagScrollListener.OnScroll(scrollY, i); // weekdag naar kolomconversie, alle dagen om problemen te voorkomen
}
});
adapter.setView(scrollView, 0, context);
} else if (isHigh) {
final float[] prevX = {0};
final int touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
HorizontalScrollView scrollView = new HorizontalScrollView(context);
scrollView.addView(container);
scrollView.setOnTouchListener((view, motionEvent) -> {
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
prevX[0] = MotionEvent.obtain(motionEvent).getX();
} else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
float eventX = motionEvent.getX();
float xDiff = Math.abs(eventX - prevX[0]);
if(xDiff > touchSlop) {
for (int i = 0; i < 10; i++) {
onDagScrollListener.OnScroll(1, i);
}
}
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
for (int i = 0; i < 10; i++) {
onDagScrollListener.OnScroll(0, i);
}
}
return false;
});
adapter.setView(scrollView, 0, context);
}
} else {
for(int i = 0; i < dagViews.size(); i++) {
adapter.setView(dagViews.get(i), i, context);
}
}
adapter.notifyDataSetChanged();
if (!weekView) {
// Ga naar de juiste dag
viewPager.setCurrentItem(showDag);
}
}
//endregion
//region AsyncThings
@Accessors(chain = true)
private class DagBuilder {
@Setter private View parentView;
@Setter private int dag = Calendar.MONDAY;
@Setter private Array<Lesuur> lessen;
@Setter private Calendar dateViewCalendar;
@Setter private SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM");
private LinearLayout linearLayout;
private ScrollView scrollView;
public View build() {
linearLayout = (LinearLayout) parentView.findViewById(R.id.rooster_dag_linearlayout);
/* Dagtitel */
TextView dagNaamTextView = (TextView) parentView.findViewById(R.id.weekdagnaam);
TextView dagDatumTextView = (TextView) parentView.findViewById(R.id.weekdagdatum);
dagNaamTextView.setText(getDayOfWeek(dag));
int week = dateViewCalendar.get(Calendar.WEEK_OF_YEAR);
dateViewCalendar.set(Calendar.DAY_OF_WEEK, dag);
dateViewCalendar.set(Calendar.WEEK_OF_YEAR, week);
dagDatumTextView.setText(dateFormat.format(dateViewCalendar.getTime()));
for(int i = 1; i <= urenCount; i++) {
int uur = i;
Array<Lesuur> lessenInUur = lessen.filter(s -> s.uur == uur);
ArrayList<RelativeLayout> lesViews = new ArrayList<>();
RelativeLayout urenContainer = null;
RelativeLayout.LayoutParams urenContainerParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
urenContainerParams.setMargins(0, 0, 0, converter.DPtoPX(10));
if(lessenInUur == null || lessenInUur.isEmpty()) { // Geen lessen -> vrij
View lesView = LayoutInflater.from(context).inflate(R.layout.rooster_tussenuur, null);
lesView.setMinimumHeight(converter.SPtoPX(89));
if(uur == urenCount) {
/*lesView.setBackgroundResource(R.drawable.basic_rect);
lesView.setPadding(0,0,0,converter.DPtoPX(1));*/
}
linearLayout.addView(lesView);
continue;
}
Array<Lesuur> vervallenLessen = lessenInUur.filter(s -> s.vervallen);
Array<Lesuur> normalLessen = lessenInUur.filter(s -> !s.vervallen);
if(vervallenLessen.isNotEmpty() && (normalLessen.isEmpty() || normalLessen.isNotEmpty() && showVervangenUren)) { // Vervallen uren verwerken
lesViews.add((RelativeLayout) makeView(vervallenLessen));
}
if(normalLessen.isNotEmpty()) {
for(Lesuur les : normalLessen) {
RelativeLayout lesLayout = (RelativeLayout) makeView(les);
if(lesLayout != null) lesViews.add(lesLayout);
}
}
boolean multipleViews = lesViews.size() > 1;
if(multipleViews) {
urenContainer = new RelativeLayout(context);
}
int reverseCounter = lesViews.size() + 1;
int counter = -1;
for (RelativeLayout lesView : lesViews) {
reverseCounter--;
counter++;
if (multipleViews) {
TextView uurCounter = (TextView) lesView.findViewById(R.id.layerCounter);
uurCounter.setVisibility(View.VISIBLE);
uurCounter.setText(new StringBuilder("(").append(reverseCounter).append("/").append(lesViews.size()).append(")"));
// Padding links/rechts zodat je uren kan zien :D
RelativeLayout.LayoutParams lesLayoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lesLayoutParams.setMargins(converter.DPtoPX(reverseCounter * 8 - 8), 0, converter.DPtoPX(counter * 8), 0);
lesView.setLayoutParams(lesLayoutParams);
}
if(multipleViews) {
urenContainer.addView(lesView);
} else {
lesView.setLayoutParams(urenContainerParams);
linearLayout.addView(lesView, urenContainerParams);
}
}
if(multipleViews) {
urenContainer.setOnClickListener(new MultipleUrenClickListener(lesViews, context));
urenContainer.setLayoutParams(urenContainerParams);
linearLayout.addView(urenContainer, urenContainerParams);
}
}
if(weekView) {
int pxPadding = converter.DPtoPX(3);
linearLayout.setPadding(pxPadding, pxPadding, pxPadding, pxPadding);
linearLayout.setMinimumWidth(converter.DPtoPX(250));
parentView.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
} else {
int pxPadding = converter.DPtoPX(10);
linearLayout.addView(getUpdateText(lastLoad));
linearLayout.setPadding(pxPadding, pxPadding, pxPadding, pxPadding);
scrollView = (ScrollView) parentView.findViewById(R.id.scrollView);
scrollView.getViewTreeObserver().addOnScrollChangedListener(() -> {
int scrollY = scrollView.getScrollY();
onDagScrollListener.OnScroll(scrollY, dag - 2); // weekdag naar kolomconversie
});
}
return parentView;
}
}
//endregion
private String getDayOfWeek(int dag) {
switch (dag) {
case Calendar.SUNDAY:
return "zondag";
case Calendar.MONDAY:
return "maandag";
case Calendar.TUESDAY:
return "dinsdag";
case Calendar.WEDNESDAY:
return "woensdag";
case Calendar.THURSDAY:
return "donderdag";
case Calendar.FRIDAY:
return "vrijdag";
case Calendar.SATURDAY:
return "zaterdag";
}
return null;
}
private View makeView(Lesuur lesuur) {
return makeView(Array.array(lesuur));
}
private View makeView(Array<Lesuur> lessen) {
LayoutInflater inflater = LayoutInflater.from(context);
View lesView;
if (lessen.get(0).vervallen) { // Vervallen lessen
lessen = lessen.filter(lesuur -> lesuur.vervallen);
lesView = inflater.inflate(R.layout.rooster_vervallen_uur, null);
lesView.setMinimumHeight(converter.SPtoPX(90));
TextView vervallenTextView = (TextView) lesView.findViewById(R.id.vervallen_tekst);
if (lessen.length() > 1) {
vervallenTextView.setText(StringUtils.join(lessen.map(s -> s.vak).toList(), " & ") + " vallen uit");
} else if(lessen.get(0).verplaatsing) {
vervallenTextView.setText(lessen.get(0).vak + " is verplaatst naar " + lessen.get(0).lokaal);
} else {
vervallenTextView.setText(lessen.get(0).vak + " valt uit");
}
} else if (lessen.length() > 1) {
throw new IllegalArgumentException("Meerdere lessen");
} else {
Lesuur lesuur = lessen.get(0);
if (lesuur.verandering) {
lesView = inflater.inflate(R.layout.rooster_uur_gewijzigd, null);
} else if(lesuur.verplaatsing) {
lesView = inflater.inflate(R.layout.rooster_uur, null);
((TextView) lesView.findViewById(R.id.rooster_lokaal)).setTextColor(Color.parseColor("#FE4A49"));
} else if(lesuur.isNew) {
lesView = inflater.inflate(R.layout.rooster_uur, null);
((TextView) lesView.findViewById(R.id.rooster_notes)).setText("Nieuwe les");
} else {
lesView = inflater.inflate(R.layout.rooster_uur, null);
}
lesView = builderFunctions.fillLesView(lesuur, lesView, inflater);
}
if (lessen.get(0).uur == urenCount) {
//lesView.findViewById(R.id.rooster_uur_linearlayout).setBackgroundResource(R.drawable.basic_rect);
}
lesView.setMinimumHeight(converter.SPtoPX(90));
ViewCompat.setElevation(lesView, converter.DPtoPX(1));
return lesView;
}
private TextView getUpdateText(long lastLoad) {
TextView textView = new TextView(context);
Date lastUpdate = new Date(lastLoad);
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm");
String lastUpdateText = "Laatst geupdate: " + dateFormat.format(lastUpdate);
if (!HelperFunctions.hasInternetConnection(context)) {
lastUpdateText = "Geen internetverbinding. " + lastUpdateText;
}
textView.setText(lastUpdateText);
return textView;
}
public interface BuilderFunctions {
View fillLesView(Lesuur lesuur, View lesView, LayoutInflater inflater);
}
public interface OnDagScrollListener {
void OnScroll(int scrollY, int dag);
}
}