/**
 * Copyright (c) 2012 Todoroo Inc
 *
 * See the file "LICENSE" for the full license governing this code.
 */
package com.todoroo.astrid.gcal;

import java.util.ArrayList;
import java.util.Collections;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.timsu.astrid.R;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.ExceptionService;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gcal.Calendars.CalendarResult;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.ui.PopupControlSet;

/**
 * Control Set for managing repeats
 *
 * @author Tim Su <tim@todoroo.com>
 *
 */
public class GCalControlSet extends PopupControlSet {

    // --- instance variables

    @Autowired
    private ExceptionService exceptionService;

    private Uri calendarUri = null;

    private final CalendarResult calendars;
    private boolean hasEvent = false;
    private Spinner calendarSelector;
    private final int title;

    public GCalControlSet(final Activity activity, int viewLayout, int displayViewLayout, int title) {
        super(activity, viewLayout, displayViewLayout, title);
        DependencyInjectionService.getInstance().inject(this);
        this.title = title;
        calendars = Calendars.getCalendars();
        getView(); // Hack to force initialized
    }

    @Override
    protected void afterInflate() {
        ((LinearLayout) getDisplayView()).addView(getView()); //hack for spinner

        this.calendarSelector = (Spinner) getView().findViewById(R.id.calendars);
        ArrayList<String> items = new ArrayList<String>();
        Collections.addAll(items, calendars.calendars);
        items.add(0, activity.getString(R.string.gcal_TEA_nocal));

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity,
                android.R.layout.simple_spinner_item, items.toArray(new String[items.size()]));

        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        calendarSelector.setPromptId(title);
        calendarSelector.setAdapter(adapter);
        resetCalendarSelector();
        calendarSelector.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> arg0, View arg1,
                    int arg2, long arg3) {
                refreshDisplayView();
            }

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

    @Override
    protected void readFromTaskOnInitialize() {
        String uri = GCalHelper.getTaskEventUri(model);
        if(!TextUtils.isEmpty(uri)) {
            try {
                calendarUri = Uri.parse(uri);

                // try to load calendar
                ContentResolver cr = activity.getContentResolver();
                Cursor cursor = cr.query(calendarUri, new String[] { "dtstart" }, null, null, null); //$NON-NLS-1$
                try {
                    boolean deleted = cursor.getCount() == 0;

                    if(deleted) {
                        calendarUri = null;
                        return;
                    }
                } finally {
                    cursor.close();
                }

                hasEvent = true;
            } catch (Exception e) {
                exceptionService.reportError("unable-to-parse-calendar: " +  //$NON-NLS-1$
                        model.getValue(Task.CALENDAR_URI), e);
            }
        } else {
            hasEvent = false;
            calendarUri = null;
        }
        refreshDisplayView();
    }

    public void resetCalendarSelector() {
        if (calendarSelector != null)
            calendarSelector.setSelection(calendars.defaultIndex + 1); // plus 1 for the no selection item
    }

    @SuppressWarnings("nls")
    @Override
    protected String writeToModelAfterInitialized(Task task) {
        if (!task.hasDueDate())
            return null;

        boolean gcalCreateEventEnabled = Preferences.getStringValue(R.string.gcal_p_default) != null &&
                                        !Preferences.getStringValue(R.string.gcal_p_default).equals("-1");
        if ((gcalCreateEventEnabled || calendarSelector.getSelectedItemPosition() != 0) &&
                calendarUri == null) {
            StatisticsService.reportEvent(StatisticsConstants.CREATE_CALENDAR_EVENT);

            try{
                ContentResolver cr = activity.getContentResolver();

                ContentValues values = new ContentValues();
                String calendarId = calendars.calendarIds[calendarSelector.getSelectedItemPosition() - 1];
                values.put("calendar_id", calendarId);

                calendarUri = GCalHelper.createTaskEvent(task, cr, values);
                if(calendarUri != null) {
                    task.setValue(Task.CALENDAR_URI, calendarUri.toString());

                    if (calendarSelector.getSelectedItemPosition() != 0 && !hasEvent) {
                        // pop up the new event
                        Intent intent = new Intent(Intent.ACTION_EDIT, calendarUri);
                        intent.putExtra("beginTime", values.getAsLong("dtstart"));
                        intent.putExtra("endTime", values.getAsLong("dtend"));
                        activity.startActivity(intent);
                    }
                }

            } catch (Exception e) {
                exceptionService.displayAndReportError(activity,
                        activity.getString(R.string.gcal_TEA_error), e);
            }
        } else if(calendarUri != null) {
            try {
                ContentValues updateValues = new ContentValues();

                // check if we need to update the item
                ContentValues setValues = task.getSetValues();
                if(setValues.containsKey(Task.TITLE.name))
                    updateValues.put("title", task.getValue(Task.TITLE));
                if(setValues.containsKey(Task.NOTES.name))
                    updateValues.put("description", task.getValue(Task.NOTES));
                if(setValues.containsKey(Task.DUE_DATE.name) || setValues.containsKey(Task.ESTIMATED_SECONDS.name))
                    GCalHelper.createStartAndEndDate(task, updateValues);

                ContentResolver cr = activity.getContentResolver();
                if(cr.update(calendarUri, updateValues, null, null) > 0)
                    return activity.getString(R.string.gcal_TEA_calendar_updated);
            } catch (Exception e) {
                exceptionService.reportError("unable-to-update-calendar: " +  //$NON-NLS-1$
                        task.getValue(Task.CALENDAR_URI), e);
            }
        }

        return null;
    }

    @SuppressWarnings("nls")
    private void viewCalendarEvent() {
        if(calendarUri == null)
            return;

        ContentResolver cr = activity.getContentResolver();
        Intent intent = new Intent(Intent.ACTION_EDIT, calendarUri);
        Cursor cursor = cr.query(calendarUri, new String[] { "dtstart", "dtend" },
                null, null, null);
        try {
            if(cursor.getCount() == 0) {
                // event no longer exists, recreate it
                calendarUri = null;
                writeToModel(model);
                return;
            }
            cursor.moveToFirst();
            intent.putExtra("beginTime", cursor.getLong(0));
            intent.putExtra("endTime", cursor.getLong(1));

        } catch (Exception e) {
            Log.e("gcal-error", "Error opening calendar", e); //$NON-NLS-1$ //$NON-NLS-2$
            Toast.makeText(activity, R.string.gcal_TEA_error, Toast.LENGTH_LONG).show();
        } finally {
            cursor.close();
        }

        activity.startActivity(intent);
    }

    @Override
    protected void refreshDisplayView() {
        TextView calendar = (TextView) getDisplayView().findViewById(R.id.calendar_display_which);
        if (initialized) {
            if (hasEvent) {
                calendar.setText(R.string.gcal_TEA_has_event);
            } else if (calendarSelector.getSelectedItemPosition() != 0) {
                calendar.setText((String)calendarSelector.getSelectedItem());
            } else {
                calendar.setText(R.string.gcal_TEA_none_selected);
            }
        } else {
            int index = calendars.defaultIndex;
            if (!TextUtils.isEmpty(model.getValue(Task.CALENDAR_URI))) {
                calendar.setText(R.string.gcal_TEA_has_event);
            } else if (index >= 0 && index < calendars.calendars.length) {
                calendar.setText(calendars.calendars[index]);
            } else {
                calendar.setText(R.string.gcal_TEA_none_selected);
            }
        }
    }

    @Override
    protected OnClickListener getDisplayClickListener() {
        return new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (calendarSelector == null)
                    getView(); // Force load
                if (!hasEvent) {
                    calendarSelector.performClick();
                } else {
                    viewCalendarEvent();
                }
            }
        };
    }
}
