package org.deke.risk.riskahead.fragment;

import android.app.DatePickerDialog;
import android.app.Dialog;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import android.app.TimePickerDialog;
import android.content.Context;
import android.os.Bundle;
import androidx.fragment.app.FragmentManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TimePicker;

import com.google.firebase.crashlytics.FirebaseCrashlytics;

import org.deke.risk.riskahead.R;
import org.deke.risk.riskahead.ReportWFActivity;
import org.deke.risk.riskahead.helper.IncidentReport;
import org.deke.risk.riskahead.adapter.SpinnerHintAdapter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 *
 * (C) Copyright 2016 RiskAhead (http://www.riskahead.net)
 * Developer & Contributor: Dennis Thießen (dennis.thiessen@riskahead.net)
 * Date of Release: 10.02.2016
 *
 */
public class ReportWF_2_Fragment extends BaseReportWFFragment {
    private final static int NOW = 1;
    private final static int PERIODIC = 2;
    private final static int DATETIME = 3;
    private final static int DATETIMEAREA = 4;

    private final static String TAG = ReportWF_2_Fragment.class.getSimpleName();

    private View viewFragment;

    private Spinner timeCategory;
    private Spinner timeSubCategory;

    private static EditText inputTimeFrom;
    private static EditText inputDateFrom;
    private static EditText inputTimeTo;
    private static EditText inputDateTo;

    private static EditText tmpInput;

    private IncidentReport incident;

    private OnInputFinishedListener mCallback;

    public static boolean tmpIsToDate = false;
    public static boolean tmpIsToTime = false;

    private DialogFragment timePickerFragment;
    private DialogFragment datePickerFragment;

    public interface OnInputFinishedListener {
        void onInputFinished(boolean finished);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        viewFragment = inflater.inflate(R.layout.fragment_reportwf_2, container, false);

        initInputElements();
        setMainSpinnerValues(R.array.cat_time_main);

        return viewFragment;
    }

    @Override
    public IncidentReport getCurrentInput() {
        saveInput();
        return incident;
    }

    private void initInputElements() {
        initLayoutFromDateTime();
        initLayoutToDateTime();

        timeCategory = viewFragment.findViewById(R.id.dd_reportwf_2_time_main);
        timeSubCategory = viewFragment.findViewById(R.id.dd_reportwf_2_time_sub);

        timeSubCategory.setVisibility(View.INVISIBLE);

        timeCategory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                int stringId = 0;

                switch (position) {
                    case NOW:
                        viewFragment.findViewById(R.id.ll_report_from_time).setVisibility(View.INVISIBLE);
                        viewFragment.findViewById(R.id.ll_report_to_time).setVisibility(View.INVISIBLE);
                        viewFragment.findViewById(R.id.dd_reportwf_2_time_sub).setVisibility(View.INVISIBLE);

                        inputDateFrom.setText(new SimpleDateFormat("yyyy-MM-dd", Locale.US).format(Calendar.getInstance().getTime()));
                        inputTimeFrom.setText(new SimpleDateFormat("HH:mm", Locale.US).format(Calendar.getInstance().getTime()));
                        break;
                    case PERIODIC:
                        viewFragment.findViewById(R.id.ll_report_from_time).setVisibility(View.INVISIBLE);
                        viewFragment.findViewById(R.id.ll_report_to_time).setVisibility(View.INVISIBLE);

                        stringId = R.array.cat_time_sub_periodical;
                        break;
                    case DATETIME:
                        viewFragment.findViewById(R.id.ll_report_from_time).setVisibility(View.VISIBLE);
                        viewFragment.findViewById(R.id.ll_report_to_time).setVisibility(View.INVISIBLE);
                        viewFragment.findViewById(R.id.dd_reportwf_2_time_sub).setVisibility(View.INVISIBLE);
                        break;
                    case DATETIMEAREA:
                        viewFragment.findViewById(R.id.ll_report_from_time).setVisibility(View.VISIBLE);
                        viewFragment.findViewById(R.id.ll_report_to_time).setVisibility(View.VISIBLE);
                        viewFragment.findViewById(R.id.dd_reportwf_2_time_sub).setVisibility(View.INVISIBLE);
                        break;
                    default:
                        viewFragment.findViewById(R.id.ll_report_from_time).setVisibility(View.INVISIBLE);
                        viewFragment.findViewById(R.id.ll_report_to_time).setVisibility(View.INVISIBLE);
                        viewFragment.findViewById(R.id.dd_reportwf_2_time_sub).setVisibility(View.INVISIBLE);

                        inputDateFrom.setText(new SimpleDateFormat("yyyy-MM-dd", Locale.US).format(Calendar.getInstance().getTime()));
                        inputTimeFrom.setText(new SimpleDateFormat("HH:mm", Locale.US).format(Calendar.getInstance().getTime()));
                        break;
                }

                if (((SpinnerHintAdapter) timeCategory.getAdapter()).isInInitialState()) {
                    timeSubCategory.setVisibility(View.INVISIBLE);
                } else {
                    if (stringId != 0) {
                        timeSubCategory.setVisibility(View.VISIBLE);
                        setSubSpinnerValues(stringId);
                    }

                    checkIfFinished();
                }


            }

            @Override
            public void onNothingSelected(AdapterView<?> parentView) {
                // do nothing
            }
        });

        timeSubCategory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if (!((SpinnerHintAdapter) timeSubCategory.getAdapter()).isInInitialState()) {
                    checkIfFinished();
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
    }

    private void setMainSpinnerValues(int stringId) {
        ReportWFActivity activity = (ReportWFActivity) getActivity();
        if(activity != null){
            ArrayAdapter<CharSequence> adapter_main_1 = ArrayAdapter.createFromResource(getActivity(), stringId , android.R.layout.simple_spinner_dropdown_item);
            timeCategory.setAdapter(new SpinnerHintAdapter(adapter_main_1, R.layout.contact_spinner_row_nothing_selected, getActivity()));
        }else{
            FirebaseCrashlytics.getInstance().log("Could not get parent activity");
        }

    }

    private void setSubSpinnerValues(int stringId) {
        ArrayAdapter<CharSequence> adapter_sub_1 = ArrayAdapter.createFromResource(viewFragment.getContext(), stringId, android.R.layout.simple_spinner_dropdown_item);
        timeSubCategory.setAdapter(new SpinnerHintAdapter(adapter_sub_1, R.layout.contact_spinner_row_nothing_selected, getActivity()));

        if(incident.getFidTimeSubCategory() > 0) timeSubCategory.setSelection(incident.getFidTimeSubCategory());
    }

    private void initLayoutFromDateTime() {
        RelativeLayout rlFromTime = viewFragment.findViewById(R.id.ll_report_from_time);
        rlFromTime.setVisibility(View.INVISIBLE);

        inputDateFrom = viewFragment.findViewById(R.id.input_report_from_date);
        inputTimeFrom = viewFragment.findViewById(R.id.input_report_from_time);

        inputDateFrom.setOnClickListener(v -> {
            tmpInput = inputDateFrom;
            tmpInput.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {

                }

                @Override
                public void afterTextChanged(Editable s) {
                    checkIfFinished();
                }
            });
            showDatePickerDialog();
        });

        inputTimeFrom.setOnClickListener(v -> {
            tmpInput = inputTimeFrom;
            tmpInput.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {

                }

                @Override
                public void afterTextChanged(Editable s) {
                    checkIfFinished();
                }
            });
            showTimePickerDialog();
        });
    }

    private void initLayoutToDateTime() {
        RelativeLayout rlFromTime = viewFragment.findViewById(R.id.ll_report_to_time);
        rlFromTime.setVisibility(View.INVISIBLE);

        inputDateTo = viewFragment.findViewById(R.id.input_report_to_date);
        inputTimeTo = viewFragment.findViewById(R.id.input_report_to_time);

        inputDateTo.setOnClickListener(v -> {
            tmpInput = inputDateTo;
            tmpIsToDate = true;
            showDatePickerDialog();
        });

        inputTimeTo.setOnClickListener(v -> {
            tmpInput = inputTimeTo;
            tmpIsToTime = true;
            showTimePickerDialog();
        });
    }

    public static class TimePickerFragment extends DialogFragment implements TimePickerDialog.OnTimeSetListener {

        @Override
        @NonNull
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final Calendar c = Calendar.getInstance();
            int hour = c.get(Calendar.HOUR_OF_DAY);
            int minute = c.get(Calendar.MINUTE);

            return new TimePickerDialog(getActivity(), this, hour, minute,DateFormat.is24HourFormat(getActivity()));
        }

        public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
            tmpInput.setText(String.format(Locale.US, "%02d:%02d", hourOfDay, minute));
        }
    }

    public void showTimePickerDialog() {
        FragmentManager fm = getFragmentManager();
        if(fm != null){
            timePickerFragment = (TimePickerFragment) fm.findFragmentByTag("Pick Time");

            if(timePickerFragment == null){
                timePickerFragment = new TimePickerFragment();
            }

            timePickerFragment.show(fm, "Pick Time");
        }else{
            FirebaseCrashlytics.getInstance().log("Could not get FragmentManager");
        }
    }

    public static class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {

        @Override
        @NonNull
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final Calendar c = Calendar.getInstance();
            int year = c.get(Calendar.YEAR);
            int month = c.get(Calendar.MONTH);
            int day = c.get(Calendar.DAY_OF_MONTH);

            ReportWFActivity activity = null;

            if(tmpIsToDate && inputDateFrom.getText().length() > 0){
                try {
                    activity = (ReportWFActivity) getActivity();
                    if(activity != null){
                        DatePickerDialog tmpDialog = new DatePickerDialog(activity, this, year, month, day);
                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
                        Date tmpFromDate = simpleDateFormat.parse(inputDateFrom.getText().toString());
                        tmpDialog.getDatePicker().setMinDate(tmpFromDate.getTime());
                        tmpIsToDate = false;
                        return tmpDialog;
                    }else{
                        FirebaseCrashlytics.getInstance().log("Could not get parent Activity");
                    }

                } catch (ParseException e) {
                    FirebaseCrashlytics.getInstance().log("Exception caught");
                    FirebaseCrashlytics.getInstance().recordException(e);
                }
            }

            if(activity != null) {
                return new DatePickerDialog(activity, this, year, month, day);
            }else{
                FirebaseCrashlytics.getInstance().log("Could not get parent Activity and therefore trying again to retrieve parent");
                return new DatePickerDialog(getActivity(),this, year, month, day);
            }
        }

        public void onDateSet(DatePicker view, int year, int month, int day) {
            tmpInput.setText(String.format(Locale.US, "%04d-%02d-%02d",year, month + 1, day));
        }
    }

    public void showDatePickerDialog() {
        FragmentManager fm = getFragmentManager();
        if(fm != null){
            datePickerFragment = (DatePickerFragment) fm.findFragmentByTag("Pick Date");

            if(datePickerFragment == null){
                datePickerFragment = new DatePickerFragment();
            }

            datePickerFragment.show(fm, "Pick Date");
        }else{
            FirebaseCrashlytics.getInstance().log("Could not get FragmentManager");
        }
    }

    private void checkIfFinished(){
        boolean isTimeCategoryFilled = false;
        boolean isSubCategoryFilled = false;
        boolean isFromDateFilled = false;
        boolean isToDateFilled = false;

        if(incident != null){

            if((timeCategory.getSelectedItemPosition() > 0) && timeCategory.getVisibility() == View.VISIBLE){
                isTimeCategoryFilled = true;
            }

            if(timeSubCategory.isShown()){
                isSubCategoryFilled = (timeSubCategory.getSelectedItemPosition() > 0);
            }else{
                isSubCategoryFilled = true;
            }

            if(inputDateFrom.isShown()){
                 isFromDateFilled = inputDateFrom.getText().toString().trim().length() > 0;
            }else{
                isFromDateFilled = true;
            }

            if(inputDateTo.isShown()){
                isToDateFilled = inputDateTo.getText().toString().trim().length() > 0;
            }else{
                isToDateFilled = true;
            }

        }

        mCallback.onInputFinished(isTimeCategoryFilled && isSubCategoryFilled && isFromDateFilled && isToDateFilled);
    }

    @Override
    public void onResume() {
        super.onResume();

        ReportWFActivity activity = (ReportWFActivity) getActivity();
        if(activity != null){
            incident = activity.getIncident();
        }else{
            FirebaseCrashlytics.getInstance().log("Could not retrieve parent activity");
        }


        if(incident != null){
            if(incident.getFidTimeCategory() != 0){
                timeCategory.setSelection(incident.getFidTimeCategory());
            }

            if(incident.getFromDate() != null && !incident.getFromDate().equals("")){
                inputDateFrom.setText(incident.getFromDate());
            }

            if(incident.getFromTime() != null && !incident.getFromTime().equals("")){
                inputTimeFrom.setText(incident.getFromTime());
            }

            if(incident.getToDate() != null && !incident.getToDate().equals("")){
                inputDateTo.setText(incident.getToDate());
            }

            if(incident.getToTime() != null && !incident.getToTime().equals("")){
                inputDateTo.setText(incident.getToDate());
            }
        }

        checkIfFinished();
    }

    @Override
    public void onStop() {
        super.onStop();
        //invalidate the DialogFragment to avoid stupid memory leak
        if (timePickerFragment != null) {
            if (timePickerFragment.isVisible()) {
                timePickerFragment.dismiss();
            }
            timePickerFragment = null;
        }

        if (datePickerFragment != null) {
            if (datePickerFragment.isVisible()) {
                datePickerFragment.dismiss();
            }
            datePickerFragment = null;
        }
    }

    @Override
    public void onPause() {
        super.onPause();

        saveInput();
    }

    public void saveInput() {

        incident.setFidTimeCategory(timeCategory.getSelectedItemPosition());
        incident.setFidTimeSubCategory(timeSubCategory.getSelectedItemPosition());
        incident.setFromDate(inputDateFrom.getText().toString());
        incident.setFromTime(inputTimeFrom.getText().toString());
        incident.setToDate(inputDateTo.getText().toString());
        incident.setToTime(inputTimeTo.getText().toString());

        ReportWFActivity activity = (ReportWFActivity) getActivity();
        if(activity != null){
            activity.setIncident(incident);
        }else{
            FirebaseCrashlytics.getInstance().log("Could not get parent Activity");
        }

    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);

        try {
            mCallback = (OnInputFinishedListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString()
                    + " must implement OnInputFinishedListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }
}
