package com.jens.automation2;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.provider.CalendarContract;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.jens.automation2.receivers.CalendarReceiver;

import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;

public class ActivityManageTriggerCalendar extends Activity
{
    CheckBox chkCalendarEventActive, chkCalendarAvailabilityBusy, chkCalendarAvailabilityFree, chkCalendarAvailabilityTentative, chkCalendarAvailabilityOutOfOffice, chkCalendarAvailabilityWorkingElsewhere, chkCalendarAllDayEvent, chkCalendarEvaluateAllDayEvent, chkCalendarEvaluateReoccurring, chkCalendarReoccurring;
    Spinner spinnerCalendarTitleDirection, spinnerCalendarLocationDirection, spinnerCalendarDescriptionDirection;
    EditText etCalendarTitle, etCalendarLocation, etCalendarDescription;
    LinearLayout llCalendarSelection;
    Button bSaveTriggerCalendar;
    List<CheckBox> checkboxesCalendars = new ArrayList<>();
    final static String separator = ",";
    TextView tvMissingCalendarHint;

    private static String[] directions;
    ArrayAdapter<String> directionSpinnerAdapter;
    public static int requestCodePermissionReadCalendar = 815;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        Miscellaneous.setDisplayLanguage(this);
        Miscellaneous.setUiTheme(this);
        setContentView(R.layout.activity_manage_trigger_calendar);

        chkCalendarEventActive = (CheckBox) findViewById(R.id.chkCalendarEventActive);
        spinnerCalendarTitleDirection = (Spinner)findViewById(R.id.spinnerCalendarTitleDirection);
        spinnerCalendarLocationDirection = (Spinner)findViewById(R.id.spinnerCalendarLocationDirection);
        spinnerCalendarDescriptionDirection = (Spinner)findViewById(R.id.spinnerCalendarDescriptionDirection);
        chkCalendarAllDayEvent = (CheckBox)findViewById(R.id.chkCalendarAllDayEvent);
        chkCalendarAvailabilityBusy = (CheckBox)findViewById(R.id.chkCalendarAvailabilityBusy);
        chkCalendarAvailabilityFree = (CheckBox)findViewById(R.id.chkCalendarAvailabilityFree);
        chkCalendarAvailabilityTentative = (CheckBox)findViewById(R.id.chkCalendarAvailabilityTentative);
        chkCalendarAvailabilityOutOfOffice = (CheckBox)findViewById(R.id.chkCalendarAvailabilityOutOfOffice);
        chkCalendarAvailabilityWorkingElsewhere = (CheckBox)findViewById(R.id.chkCalendarAvailabilityWorkingElsewhere);
        chkCalendarEvaluateAllDayEvent = (CheckBox)findViewById(R.id.chkCalendarEvaluateAllDayEvent);
        chkCalendarEvaluateReoccurring = (CheckBox)findViewById(R.id.chkCalendarEvaluateReoccurring);
        chkCalendarReoccurring = (CheckBox)findViewById(R.id.chkCalendarReoccurring);

        tvMissingCalendarHint = (TextView) findViewById(R.id.tvMissingCalendarHint);

        llCalendarSelection = (LinearLayout)findViewById(R.id.llCalendarSelection);

        etCalendarTitle = (EditText)findViewById(R.id.etCalendarTitle);
        etCalendarLocation = (EditText)findViewById(R.id.etCalendarLocation);
        etCalendarDescription = (EditText)findViewById(R.id.etCalendarDescription);

        bSaveTriggerCalendar = (Button)findViewById(R.id.bSaveTriggerCalendar);

        directions = new String[] {
                getResources().getString(R.string.directionStringEquals),
                getResources().getString(R.string.directionStringContains),
                getResources().getString(R.string.directionStringDoesNotContain),
                getResources().getString(R.string.directionStringStartsWith),
                getResources().getString(R.string.directionStringEndsWith),
                getResources().getString(R.string.directionStringNotEquals)
        };
        directionSpinnerAdapter = new ArrayAdapter<>(this, R.layout.text_view_for_poi_listview_mediumtextsize, ActivityManageTriggerCalendar.directions);
        spinnerCalendarTitleDirection.setAdapter(directionSpinnerAdapter);
        spinnerCalendarLocationDirection.setAdapter(directionSpinnerAdapter);
        spinnerCalendarDescriptionDirection.setAdapter(directionSpinnerAdapter);
        directionSpinnerAdapter.notifyDataSetChanged();

        chkCalendarEvaluateAllDayEvent.setChecked(false);
        chkCalendarAllDayEvent.setEnabled(false);
        chkCalendarEvaluateAllDayEvent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean checked)
            {
                chkCalendarAllDayEvent.setEnabled(checked);
            }
        });

        chkCalendarEvaluateReoccurring.setChecked(false);
        chkCalendarReoccurring.setEnabled(false);
        chkCalendarEvaluateReoccurring.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean checked)
            {
                chkCalendarReoccurring.setEnabled(checked);
            }
        });

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        {
            if(ActivityPermissions.havePermission(Manifest.permission.READ_CALENDAR, ActivityManageTriggerCalendar.this) || ActivityPermissions.havePermission(Manifest.permission.WRITE_CALENDAR, ActivityManageTriggerCalendar.this))
                populateCalenderCheckboxes();
            else
            {
                AlertDialog.Builder builder = new AlertDialog.Builder(ActivityManageTriggerCalendar.this);
                builder.setTitle(getResources().getString(R.string.info));
                builder.setMessage(getResources().getString(R.string.permissionCalendarRequired));
                builder.setNegativeButton(getResources().getString(R.string.cancel), new DialogInterface.OnClickListener()
                {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i)
                    {
                        ActivityManageTriggerCalendar.this.finish();
                    }
                });
                builder.setPositiveButton(getResources().getString(R.string.ok), new DialogInterface.OnClickListener()
                {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i)
                    {
                        requestPermissions(new String[]{ Manifest.permission.READ_CALENDAR } , requestCodePermissionReadCalendar);
                    }
                });
                builder.show();
            }
        }
        else
            populateCalenderCheckboxes();

        chkCalendarEventActive.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean checked)
            {
                if(checked)
                    chkCalendarEventActive.setText(R.string.eventIsCurrentlyHappening);
                else
                    chkCalendarEventActive.setText(R.string.eventIsCurrentlyNotHappening);
            }
        });

        chkCalendarAllDayEvent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean checked)
            {
                if(checked)
                    chkCalendarAllDayEvent.setText(getResources().getString(R.string.allDayEventTrue));
                else
                    chkCalendarAllDayEvent.setText(getResources().getString(R.string.allDayEventFalse));
            }
        });

        chkCalendarReoccurring.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean checked)
            {
                if(checked)
                    chkCalendarReoccurring.setText(R.string.reoccurringTrue);
                else
                    chkCalendarReoccurring.setText(R.string.reoccurringFalse);
            }
        });

        bSaveTriggerCalendar.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                String titleDir = Trigger.getMatchCode(spinnerCalendarTitleDirection.getSelectedItem().toString());
                String title = etCalendarTitle.getText().toString();
                String descriptionDir = Trigger.getMatchCode(spinnerCalendarDescriptionDirection.getSelectedItem().toString());
                String description = etCalendarDescription.getText().toString();
                String locationDir = Trigger.getMatchCode(spinnerCalendarLocationDirection.getSelectedItem().toString());
                String location = etCalendarLocation.getText().toString();

                List<String> availabilityList = new ArrayList<>();
                if(chkCalendarAvailabilityBusy.isChecked())
                    availabilityList.add(String.valueOf(CalendarContract.Events.AVAILABILITY_BUSY));

                if(chkCalendarAvailabilityFree.isChecked())
                    availabilityList.add(String.valueOf(CalendarContract.Events.AVAILABILITY_FREE));

                if(chkCalendarAvailabilityTentative.isChecked())
                    availabilityList.add(String.valueOf(CalendarContract.Events.AVAILABILITY_TENTATIVE));

                if(chkCalendarAvailabilityOutOfOffice.isChecked())
                    availabilityList.add(String.valueOf(CalendarReceiver.AVAILABILITY_OUT_OF_OFFICE));

                if(chkCalendarAvailabilityWorkingElsewhere.isChecked())
                    availabilityList.add(String.valueOf(CalendarReceiver.AVAILABILITY_WORKING_ELSEWHERE));

                List<CalendarReceiver.AndroidCalendar> selectedCalendarsList = new ArrayList<>();
                for(CheckBox calCheckbox : checkboxesCalendars)
                {
                    if(calCheckbox.isChecked())
                        selectedCalendarsList.add((CalendarReceiver.AndroidCalendar) calCheckbox.getTag());
                }
                List<String> selectedCalendarsIdArray = new ArrayList<>();
                for(CalendarReceiver.AndroidCalendar cal : selectedCalendarsList)
                    selectedCalendarsIdArray.add(String.valueOf(cal.calendarId));

                String returnString =
                        titleDir + Trigger.triggerParameter2Split + title + Trigger.triggerParameter2Split +
                        descriptionDir + Trigger.triggerParameter2Split + description + Trigger.triggerParameter2Split +
                        locationDir + Trigger.triggerParameter2Split + location + Trigger.triggerParameter2Split +
                        String.valueOf(chkCalendarEvaluateAllDayEvent.isChecked()) + Trigger.triggerParameter2Split +
                        String.valueOf(chkCalendarAllDayEvent.isChecked()) + Trigger.triggerParameter2Split +
                        String.valueOf(chkCalendarEvaluateReoccurring.isChecked()) + Trigger.triggerParameter2Split +
                        String.valueOf(chkCalendarReoccurring.isChecked()) + Trigger.triggerParameter2Split +
                        Miscellaneous.explode(separator, availabilityList.toArray(new String[availabilityList.size()])) + Trigger.triggerParameter2Split +
                        Miscellaneous.explode(separator, selectedCalendarsIdArray.toArray(new String[selectedCalendarsIdArray.size()]));

                Intent data = new Intent();
                data.putExtra(ActivityManageRule.intentNameTriggerParameter1, chkCalendarEventActive.isChecked());
                data.putExtra(ActivityManageRule.intentNameTriggerParameter2, returnString);
                ActivityManageTriggerCalendar.this.setResult(RESULT_OK, data);

                finish();
            }
        });

        Intent inputIntent = getIntent();
        if(inputIntent.hasExtra(ActivityManageRule.intentNameTriggerParameter1))
            loadValuesIntoGui(inputIntent);
    }

    private void populateCalenderCheckboxes()
    {
        List<CalendarReceiver.AndroidCalendar> calList = CalendarReceiver.readCalendars(ActivityManageTriggerCalendar.this);

        if(calList != null)
        {
            if(calList.size() > 0)
            {
                for (CalendarReceiver.AndroidCalendar cal : calList)
                {
                    CheckBox oneCalCheckbox = new CheckBox(ActivityManageTriggerCalendar.this);
                    oneCalCheckbox.setText(cal.toString());
                    oneCalCheckbox.setTag(cal);
                    llCalendarSelection.addView(oneCalCheckbox);
                    checkboxesCalendars.add(oneCalCheckbox);
                }
            }
            else
                Miscellaneous.messageBox(getResources().getString(R.string.warning), getResources().getString(R.string.noCalendarsOnYourDevice), ActivityManageTriggerCalendar.this).show();
        }
        else
            Miscellaneous.messageBox(getResources().getString(R.string.warning), getResources().getString(R.string.errorReadingCalendars), ActivityManageTriggerCalendar.this).show();
    }

    void loadValuesIntoGui(Intent data)
    {
        try
        {
            if (data.hasExtra(ActivityManageRule.intentNameTriggerParameter1))
                chkCalendarEventActive.setChecked(data.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true));

            if (data.hasExtra(ActivityManageRule.intentNameTriggerParameter2))
            {
                String input[] = data.getStringExtra(ActivityManageRule.intentNameTriggerParameter2).split(Trigger.triggerParameter2Split, -1);
            /*
                0 = titleDir
                1 = title
                2 = descriptionDir
                3 = description
                4 = locationDir
                5 = location
                6 = evaluate all day event
                7 = all day event
                8 = evaluate reoccurring
                9 = reoccurring
                10 = availability list
                11 = calendars list
            */

                for (int i = 0; i < directions.length; i++)
                {
                    if (Trigger.getMatchCode(directions[i]).equalsIgnoreCase(input[0]))
                        spinnerCalendarTitleDirection.setSelection(i);

                    if (Trigger.getMatchCode(directions[i]).equalsIgnoreCase(input[2]))
                        spinnerCalendarDescriptionDirection.setSelection(i);

                    if (Trigger.getMatchCode(directions[i]).equalsIgnoreCase(input[4]))
                        spinnerCalendarLocationDirection.setSelection(i);
                }

                etCalendarTitle.setText(input[1]);
                etCalendarDescription.setText(input[3]);
                etCalendarLocation.setText(input[5]);

                chkCalendarEvaluateAllDayEvent.setChecked(Boolean.parseBoolean(input[6]));
                chkCalendarAllDayEvent.setChecked(Boolean.parseBoolean(input[7]));

                chkCalendarEvaluateReoccurring.setChecked(Boolean.parseBoolean(input[8]));
                chkCalendarReoccurring.setChecked(Boolean.parseBoolean(input[9]));

                String[] availabilities = null;
                if (!StringUtils.isEmpty(input[10]))
                    availabilities = input[10].split(separator);

                if (availabilities != null)
                {
                    for (String avail : availabilities)
                    {
                        if (Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_BUSY)
                            chkCalendarAvailabilityBusy.setChecked(true);
                        else if (Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_FREE)
                            chkCalendarAvailabilityFree.setChecked(true);
                        else if (Integer.parseInt(avail) == CalendarContract.Events.AVAILABILITY_TENTATIVE)
                            chkCalendarAvailabilityTentative.setChecked(true);
                        else if (Integer.parseInt(avail) == CalendarReceiver.AVAILABILITY_OUT_OF_OFFICE)
                            chkCalendarAvailabilityOutOfOffice.setChecked(true);
                        else if (Integer.parseInt(avail) == CalendarReceiver.AVAILABILITY_WORKING_ELSEWHERE)
                            chkCalendarAvailabilityWorkingElsewhere.setChecked(true);
                    }
                }

                String[] calendars = null;
                if (!StringUtils.isEmpty(input[11]))
                    calendars = input[11].split(separator);

                if (calendars != null)
                {
                    List<String> usedCalendarIDs = new ArrayList<>();
                    List<String> unusedCalendarIDs = new ArrayList<>();
                    for (CheckBox checkbox : checkboxesCalendars)
                    {
                        int id = ((CalendarReceiver.AndroidCalendar) checkbox.getTag()).calendarId;
                        for (String calId : calendars)
                        {
                            if (calId.equals(String.valueOf(id)))
                            {
                                usedCalendarIDs.add(String.valueOf(id));
                                checkbox.setChecked(true);
                                break;
                            }
                        }
                    }
                    for (String calId : calendars)
                    {
                        if (!Miscellaneous.arraySearch((ArrayList<String>) usedCalendarIDs, calId, false, true))
                            unusedCalendarIDs.add(calId);
                    }
                    if (unusedCalendarIDs.size() > 0)
                    {
                /*
                    A calendar has been configured that has been deleted since. We cannot resolve it.
                    It will be removed with the next save, but we should inform this user
                    of these circumstances.
                 */

                        tvMissingCalendarHint.setText(String.format(getResources().getString(R.string.calendarsMissingHint), Miscellaneous.explode(", ", (ArrayList<String>) unusedCalendarIDs)));
                    }
                }
            }
        }
        catch (Exception e)
        {
            Miscellaneous.logEvent("e", "ActivityManagerTriggerCalender", "Error loading values into GUI: " + Log.getStackTraceString(e), 1);
            Toast.makeText(ActivityManageTriggerCalendar.this, getResources().getString(R.string.errorLoadingValues), Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
    {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if(requestCode == requestCodePermissionReadCalendar)
        {
            if(
                    permissions[0].equals(Manifest.permission.READ_CALENDAR)
                        ||
                    permissions[0].equals(Manifest.permission.WRITE_CALENDAR)
            )
            {
                if(grantResults[0] == PackageManager.PERMISSION_GRANTED)
                    populateCalenderCheckboxes();
                else
                    finish();
            }
        }
    }
}