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

import java.util.Date;

import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.SyncFlags;
import com.todoroo.astrid.data.Task;

public class DueDateTimeMigrator {

    @Autowired TaskDao taskDao;

    private static final String PREF_MIGRATED_DUE_TIMES = "migrated_due_times";  //$NON-NLS-1$
    private static final String STRFTIME_FORMAT = "%H:%M:%S"; //$NON-NLS-1$
    private static final String LEGACY_NO_TIME_STRING = "23:59:59"; //$NON-NLS-1$

    public DueDateTimeMigrator() {
        DependencyInjectionService.getInstance().inject(this);
    }

    private interface TaskDateAdjuster {
        public void adjust(Date date);
    }

    public void migrateDueTimes() {
        if (!Preferences.getBoolean(PREF_MIGRATED_DUE_TIMES, false)) {
            // Get tasks with due time (i.e. due date != 23:59:59)
            TodorooCursor<Task> tasksWithDueTime = taskDao.query(Query.select(Task.ID, Task.DUE_DATE, Task.MODIFICATION_DATE).where(
                    Criterion.and(Task.DUE_DATE.gt(0),
                            Functions.strftime(Task.DUE_DATE, STRFTIME_FORMAT).neq(LEGACY_NO_TIME_STRING))));
            try {

                // Get tasks with no due time (i.e. due date = 23:59:59)
                TodorooCursor<Task> tasksWithoutDueTime = taskDao.query(Query.select(Task.ID, Task.DUE_DATE, Task.MODIFICATION_DATE).where(
                        Criterion.and(Task.DUE_DATE.gt(0),
                                Functions.strftime(Task.DUE_DATE, STRFTIME_FORMAT).eq(LEGACY_NO_TIME_STRING))));

                tasksWithoutDueTime.getCount();
                tasksWithDueTime.getCount();

                try {
                    // Set tasks without time to 12:00:00
                    processCursor(tasksWithoutDueTime, new TaskDateAdjuster() {
                        @Override
                        public void adjust(Date date) {
                            date.setHours(12);
                            date.setMinutes(0);
                            date.setSeconds(0);
                        }
                    });

                } finally {
                    tasksWithoutDueTime.close();
                }

                // Set tasks with time to have time HH:MM:01
                processCursor(tasksWithDueTime, new TaskDateAdjuster() {
                    @Override
                    public void adjust(Date date) {
                        date.setSeconds(1);
                    }
                });

            } finally {
                tasksWithDueTime.close();
            }

            Preferences.setBoolean(PREF_MIGRATED_DUE_TIMES, true);
        }
    }

    private void processCursor(TodorooCursor<Task> cursor, TaskDateAdjuster adjuster) {
        Task curr = new Task();
        for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
            curr.readFromCursor(cursor);
            long time = curr.getValue(Task.DUE_DATE) / 1000L * 1000L;
            Date date = new Date(time);
            adjuster.adjust(date);
            curr.setValue(Task.DUE_DATE, date.getTime());
            curr.getSetValues().put(Task.MODIFICATION_DATE.name, curr.getValue(Task.MODIFICATION_DATE)); // Don't change modification date
            curr.putTransitory(SyncFlags.ACTFM_SUPPRESS_SYNC, true);
            curr.putTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC, true);
            taskDao.save(curr);
        }
    }

}
