/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.provider;

import android.content.ContentQueryMap;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;

import java.util.Map;

/**
 * The Sync provider stores information used in managing the syncing of the device,
 * including the history and pending syncs.
 * 
 * @hide
 */
public final class Sync {
    // utility class
    private Sync() {}

    /**
     * The content url for this provider.
     */
    public static final Uri CONTENT_URI = Uri.parse("content://sync");

    /**
     * Columns from the stats table.
     */
    public interface StatsColumns {
        /**
         * The sync account.
         * <P>Type: TEXT</P>
         */
        public static final String ACCOUNT = "account";

        /**
         * The content authority (contacts, calendar, etc.).
         * <P>Type: TEXT</P>
         */
        public static final String AUTHORITY = "authority";
    }

    /**
     * Provides constants and utility methods to access and use the stats table.
     */
    public static final class Stats implements BaseColumns, StatsColumns {

        // utility class
        private Stats() {}

        /**
         * The content url for this table.
         */
        public static final Uri CONTENT_URI =
                Uri.parse("content://sync/stats");

        /** Projection for the _id column in the stats table. */
        public static final String[] SYNC_STATS_PROJECTION = {_ID};
    }

    /**
     * Columns from the history table.
     */
    public interface HistoryColumns {
        /**
         * The ID of the stats row corresponding to this event.
         * <P>Type: INTEGER</P>
         */
        public static final String STATS_ID = "stats_id";

        /**
         * The source of the sync event (LOCAL, POLL, USER, SERVER).
         * <P>Type: INTEGER</P>
         */
        public static final String SOURCE = "source";

        /**
         * The type of sync event (START, STOP).
         * <P>Type: INTEGER</P>
         */
        public static final String EVENT = "event";

        /**
         * The time of the event.
         * <P>Type: INTEGER</P>
         */
        public static final String EVENT_TIME = "eventTime";

        /**
         * How long this event took. This is only valid if the EVENT is EVENT_STOP.
         * <P>Type: INTEGER</P>
         */
        public static final String ELAPSED_TIME = "elapsedTime";

        /**
         * Any additional message associated with this event.
         * <P>Type: TEXT</P>
         */
        public static final String MESG = "mesg";

        /**
         * How much activity was performed sending data to the server. This is sync adapter
         * specific, but usually is something like how many record update/insert/delete attempts
         * were carried out. This is only valid if the EVENT is EVENT_STOP.
         * <P>Type: INTEGER</P>
         */
        public static final String UPSTREAM_ACTIVITY = "upstreamActivity";

        /**
         * How much activity was performed while receiving data from the server.
         * This is sync adapter specific, but usually is something like how many
         * records were received from the server. This is only valid if the
         * EVENT is EVENT_STOP.
         * <P>Type: INTEGER</P>
         */
        public static final String DOWNSTREAM_ACTIVITY = "downstreamActivity";
    }

    /**
     * Columns from the history table.
     */
    public interface StatusColumns {
        /**
         * How many syncs were completed for this account and authority.
         * <P>Type: INTEGER</P>
         */
        public static final String NUM_SYNCS = "numSyncs";

        /**
         * How long all the events for this account and authority took.
         * <P>Type: INTEGER</P>
         */
        public static final String TOTAL_ELAPSED_TIME = "totalElapsedTime";

        /**
         * The number of syncs with SOURCE_POLL.
         * <P>Type: INTEGER</P>
         */
        public static final String NUM_SOURCE_POLL = "numSourcePoll";

        /**
         * The number of syncs with SOURCE_SERVER.
         * <P>Type: INTEGER</P>
         */
        public static final String NUM_SOURCE_SERVER = "numSourceServer";

        /**
         * The number of syncs with SOURCE_LOCAL.
         * <P>Type: INTEGER</P>
         */
        public static final String NUM_SOURCE_LOCAL = "numSourceLocal";

        /**
         * The number of syncs with SOURCE_USER.
         * <P>Type: INTEGER</P>
         */
        public static final String NUM_SOURCE_USER = "numSourceUser";

        /**
         * The time in ms that the last successful sync ended. Will be null if
         * there are no successful syncs. A successful sync is defined as one having
         * MESG=MESG_SUCCESS.
         * <P>Type: INTEGER</P>
         */
        public static final String LAST_SUCCESS_TIME = "lastSuccessTime";

        /**
         * The SOURCE of the last successful sync. Will be null if
         * there are no successful syncs. A successful sync is defined
         * as one having MESG=MESG_SUCCESS.
         * <P>Type: INTEGER</P>
         */
        public static final String LAST_SUCCESS_SOURCE = "lastSuccessSource";

        /**
         * The end time in ms of the last sync that failed since the last successful sync.
         * Will be null if there are no syncs or if the last one succeeded. A failed
         * sync is defined as one where MESG isn't MESG_SUCCESS or MESG_CANCELED.
         * <P>Type: INTEGER</P>
         */
        public static final String LAST_FAILURE_TIME = "lastFailureTime";

        /**
         * The SOURCE of the last sync that failed since the last successful sync.
         * Will be null if there are no syncs or if the last one succeeded. A failed
         * sync is defined as one where MESG isn't MESG_SUCCESS or MESG_CANCELED.
         * <P>Type: INTEGER</P>
         */
        public static final String LAST_FAILURE_SOURCE = "lastFailureSource";

        /**
         * The MESG of the last sync that failed since the last successful sync.
         * Will be null if there are no syncs or if the last one succeeded. A failed
         * sync is defined as one where MESG isn't MESG_SUCCESS or MESG_CANCELED.
         * <P>Type: STRING</P>
         */
        public static final String LAST_FAILURE_MESG = "lastFailureMesg";

        /**
         * Is set to 1 if a sync is pending, 0 if not.
         * <P>Type: INTEGER</P>
         */
        public static final String PENDING = "pending";
    }

    /**
     * Provides constants and utility methods to access and use the history
     * table.
     */
    public static class History implements BaseColumns,
                                                 StatsColumns,
                                                 HistoryColumns {

        /**
         * The content url for this table.
         */
        public static final Uri CONTENT_URI =
                Uri.parse("content://sync/history");

        /** Enum value for a sync start event. */
        public static final int EVENT_START = 0;

        /** Enum value for a sync stop event. */
        public static final int EVENT_STOP = 1;

        // TODO: i18n -- grab these out of resources.
        /** String names for the sync event types. */
        public static final String[] EVENTS = { "START", "STOP" };

        /** Enum value for a server-initiated sync. */
        public static final int SOURCE_SERVER = 0;

        /** Enum value for a local-initiated sync. */
        public static final int SOURCE_LOCAL = 1;
        /**
         * Enum value for a poll-based sync (e.g., upon connection to
         * network)
         */
        public static final int SOURCE_POLL = 2;

        /** Enum value for a user-initiated sync. */
        public static final int SOURCE_USER = 3;

        // TODO: i18n -- grab these out of resources.
        /** String names for the sync source types. */
        public static final String[] SOURCES = { "SERVER",
                                                 "LOCAL",
                                                 "POLL",
                                                 "USER" };

        // Error types
        public static final int ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
        public static final int ERROR_AUTHENTICATION = 2;
        public static final int ERROR_IO = 3;
        public static final int ERROR_PARSE = 4;
        public static final int ERROR_CONFLICT = 5;
        public static final int ERROR_TOO_MANY_DELETIONS = 6;
        public static final int ERROR_TOO_MANY_RETRIES = 7;

        // The MESG column will contain one of these or one of the Error types.
        public static final String MESG_SUCCESS = "success";
        public static final String MESG_CANCELED = "canceled";

        private static final String FINISHED_SINCE_WHERE_CLAUSE = EVENT + "=" + EVENT_STOP
                + " AND " + EVENT_TIME + ">? AND " + ACCOUNT + "=? AND " + AUTHORITY + "=?";

        public static String mesgToString(String mesg) {
            if (MESG_SUCCESS.equals(mesg)) return mesg;
            if (MESG_CANCELED.equals(mesg)) return mesg;
            switch (Integer.parseInt(mesg)) {
                case ERROR_SYNC_ALREADY_IN_PROGRESS: return "already in progress";
                case ERROR_AUTHENTICATION: return "bad authentication";
                case ERROR_IO: return "network error";
                case ERROR_PARSE: return "parse error";
                case ERROR_CONFLICT: return "conflict detected";
                case ERROR_TOO_MANY_DELETIONS: return "too many deletions";
                case ERROR_TOO_MANY_RETRIES: return "too many retries";
                default: return "unknown error";
            }
        }

        // utility class
        private History() {}

        /**
         * returns a cursor that queries the sync history in descending event time order
         * @param contentResolver the ContentResolver to use for the query
         * @return the cursor on the History table
         */
        public static Cursor query(ContentResolver contentResolver) {
            return contentResolver.query(CONTENT_URI, null, null, null, EVENT_TIME + " desc");
        }

        public static boolean hasNewerSyncFinished(ContentResolver contentResolver,
                String account, String authority, long when) {
            Cursor c = contentResolver.query(CONTENT_URI, new String[]{_ID},
                    FINISHED_SINCE_WHERE_CLAUSE,
                    new String[]{Long.toString(when), account, authority}, null);
            try {
              return c.getCount() > 0;
            } finally {
                c.close();
            }
        }
    }

    /**
     * Provides constants and utility methods to access and use the authority history
     * table, which contains information about syncs aggregated by account and authority.
     * All the HistoryColumns except for EVENT are present, plus the AuthorityHistoryColumns.
     */
    public static class Status extends History implements StatusColumns {

        /**
         * The content url for this table.
         */
        public static final Uri CONTENT_URI = Uri.parse("content://sync/status");

        // utility class
        private Status() {}

        /**
         * returns a cursor that queries the authority sync history in descending event order of
         * ACCOUNT, AUTHORITY
         * @param contentResolver the ContentResolver to use for the query
         * @return the cursor on the AuthorityHistory table
         */
        public static Cursor query(ContentResolver contentResolver) {
            return contentResolver.query(CONTENT_URI, null, null, null, ACCOUNT + ", " + AUTHORITY);
        }

        public static class QueryMap extends ContentQueryMap {
            public QueryMap(ContentResolver contentResolver,
                    boolean keepUpdated,
                    Handler handlerForUpdateNotifications) {
                super(contentResolver.query(CONTENT_URI, null, null, null, null),
                        _ID, keepUpdated, handlerForUpdateNotifications);
            }

            public ContentValues get(String account, String authority) {
                Map<String, ContentValues> rows = getRows();
                for (ContentValues values : rows.values()) {
                    if (values.getAsString(ACCOUNT).equals(account)
                            && values.getAsString(AUTHORITY).equals(authority)) {
                        return values;
                    }
                }
                return null;
            }
        }
    }

    /**
     * Provides constants and utility methods to access and use the pending syncs table
     */
    public static final class Pending implements BaseColumns,
                                                 StatsColumns {

        /**
         * The content url for this table.
         */
        public static final Uri CONTENT_URI = Uri.parse("content://sync/pending");

        // utility class
        private Pending() {}

        public static class QueryMap extends ContentQueryMap {
            public QueryMap(ContentResolver contentResolver, boolean keepUpdated,
                    Handler handlerForUpdateNotifications) {
                super(contentResolver.query(CONTENT_URI, null, null, null, null), _ID, keepUpdated,
                        handlerForUpdateNotifications);
            }

            public boolean isPending(String account, String authority) {
                Map<String, ContentValues> rows = getRows();
                for (ContentValues values : rows.values()) {
                    if (values.getAsString(ACCOUNT).equals(account)
                            && values.getAsString(AUTHORITY).equals(authority)) {
                        return true;
                    }
                }
                return false;
            }
        }
    }

    /**
     * Columns from the history table.
     */
    public interface ActiveColumns {
        /**
         * The wallclock time of when the active sync started.
         * <P>Type: INTEGER</P>
         */
        public static final String START_TIME = "startTime";
    }

    /**
     * Provides constants and utility methods to access and use the pending syncs table
     */
    public static final class Active implements BaseColumns,
                                                StatsColumns,
                                                ActiveColumns {

        /**
         * The content url for this table.
         */
        public static final Uri CONTENT_URI = Uri.parse("content://sync/active");

        // utility class
        private Active() {}

        public static class QueryMap extends ContentQueryMap {
            public QueryMap(ContentResolver contentResolver, boolean keepUpdated,
                    Handler handlerForUpdateNotifications) {
                super(contentResolver.query(CONTENT_URI, null, null, null, null), _ID, keepUpdated,
                        handlerForUpdateNotifications);
            }

            public ContentValues getActiveSyncInfo() {
                Map<String, ContentValues> rows = getRows();
                for (ContentValues values : rows.values()) {
                    return values;
                }
                return null;
            }

            public String getSyncingAccount() {
                ContentValues values = getActiveSyncInfo();
                return (values == null) ? null : values.getAsString(ACCOUNT);
            }

            public String getSyncingAuthority() {
                ContentValues values = getActiveSyncInfo();
                return (values == null) ? null : values.getAsString(AUTHORITY);
            }

            public long getSyncStartTime() {
                ContentValues values = getActiveSyncInfo();
                return (values == null) ? -1 : values.getAsLong(START_TIME);
            }
        }
    }

    /**
     * Columns in the settings table, which holds key/value pairs of settings.
     */
    public interface SettingsColumns {
        /**
         * The key of the setting
         * <P>Type: TEXT</P>
         */
        public static final String KEY = "name";

        /**
         * The value of the settings
         * <P>Type: TEXT</P>
         */
        public static final String VALUE = "value";
    }

    /**
     * Provides constants and utility methods to access and use the settings
     * table.
     */
    public static final class Settings implements BaseColumns, SettingsColumns {
        /**
         * The Uri of the settings table. This table behaves a little differently than
         * normal tables. Updates are not allowed, only inserts, and inserts cause a replace
         * to be performed, which first deletes the row if it is already present.
         */
        public static final Uri CONTENT_URI = Uri.parse("content://sync/settings");

        /** controls whether or not the device listens for sync tickles */
        public static final String SETTING_LISTEN_FOR_TICKLES = "listen_for_tickles";

        /** controls whether or not the device connect to Google in background for various
         *  stuff, including GTalk, checkin, Market and data sync ...
         */
        public static final String SETTING_BACKGROUND_DATA = "background_data";

        /** controls whether or not the individual provider is synced when tickles are received */
        public static final String SETTING_SYNC_PROVIDER_PREFIX = "sync_provider_";

        /** query column project */
        private static final String[] PROJECTION = { KEY, VALUE };

        /**
         * Convenience function for updating a single settings value as a
         * boolean. This will either create a new entry in the table if the
         * given name does not exist, or modify the value of the existing row
         * with that name.  Note that internally setting values are always
         * stored as strings, so this function converts the given value to a
         * string before storing it.
         *
         * @param contentResolver the ContentResolver to use to access the settings table
         * @param name The name of the setting to modify.
         * @param val The new value for the setting.
         */
        static private void putBoolean(ContentResolver contentResolver, String name, boolean val) {
            ContentValues values = new ContentValues();
            values.put(KEY, name);
            values.put(VALUE, Boolean.toString(val));
            // this insert is translated into an update by the underlying Sync provider
            contentResolver.insert(CONTENT_URI, values);
        }

        /**
         * Convenience function for getting a setting value as a boolean without using the
         * QueryMap for light-weight setting querying.
         * @param contentResolver The ContentResolver for querying the setting.
         * @param name The name of the setting to query
         * @param def The default value for the setting.
         * @return The value of the setting.
         */
        static public boolean getBoolean(ContentResolver contentResolver,
                String name, boolean def) {
            Cursor cursor = contentResolver.query(
                    CONTENT_URI,
                    PROJECTION,
                    KEY + "=?",
                    new String[] { name },
                    null);
            try {
                if (cursor != null && cursor.moveToFirst()) {
                    return Boolean.parseBoolean(cursor.getString(1));
                }
            } finally {
                if (cursor != null) cursor.close();
            }
            return def;
        }

        /**
         * A convenience method to set whether or not the provider is synced when
         * it receives a network tickle.
         *
         * @param contentResolver the ContentResolver to use to access the settings table
         * @param providerName the provider whose behavior is being controlled
         * @param sync true if the provider should be synced when tickles are received for it
         */
        static public void setSyncProviderAutomatically(ContentResolver contentResolver,
                String providerName, boolean sync) {
            putBoolean(contentResolver, SETTING_SYNC_PROVIDER_PREFIX + providerName, sync);
        }

        /**
         * A convenience method to set whether or not the device should listen to tickles.
         *
         * @param contentResolver the ContentResolver to use to access the settings table
         * @param flag true if it should listen.
         */
        static public void setListenForNetworkTickles(ContentResolver contentResolver,
                boolean flag) {
            putBoolean(contentResolver, SETTING_LISTEN_FOR_TICKLES, flag);
        }

        /**
         * A convenience method to set whether or not the device should connect to Google
         * in background.
         *
         * @param contentResolver the ContentResolver to use to access the settings table
         * @param flag true if it should connect.
         */
        static public void setBackgroundData(ContentResolver contentResolver,
                boolean flag) {
            putBoolean(contentResolver, SETTING_BACKGROUND_DATA, flag);
        }

        public static class QueryMap extends ContentQueryMap {
            private ContentResolver mContentResolver;

            public QueryMap(ContentResolver contentResolver, boolean keepUpdated,
                    Handler handlerForUpdateNotifications) {
                super(contentResolver.query(CONTENT_URI, null, null, null, null), KEY, keepUpdated,
                        handlerForUpdateNotifications);
                mContentResolver = contentResolver;
            }

            /**
             * Check if the provider should be synced when a network tickle is received
             * @param providerName the provider whose setting we are querying
             * @return true of the provider should be synced when a network tickle is received
             */
            public boolean getSyncProviderAutomatically(String providerName) {
                return getBoolean(SETTING_SYNC_PROVIDER_PREFIX + providerName, true);
            }

            /**
             * Set whether or not the provider is synced when it receives a network tickle.
             *
             * @param providerName the provider whose behavior is being controlled
             * @param sync true if the provider should be synced when tickles are received for it
             */
            public void setSyncProviderAutomatically(String providerName, boolean sync) {
                Settings.setSyncProviderAutomatically(mContentResolver, providerName, sync);
            }

            /**
             * Set whether or not the device should listen for tickles.
             *
             * @param flag true if it should listen.
             */
            public void setListenForNetworkTickles(boolean flag) {
                Settings.setListenForNetworkTickles(mContentResolver, flag);
            }

            /**
             * Check if the device should listen to tickles.

             * @return true if it should
             */
            public boolean getListenForNetworkTickles() {
                return getBoolean(SETTING_LISTEN_FOR_TICKLES, true);
            }

            /**
             * Set whether or not the device should connect to Google in background
             *
             * @param flag true if it should
             */
            public void setBackgroundData(boolean flag) {
                Settings.setBackgroundData(mContentResolver, flag);
            }

            /**
             * Check if the device should connect to Google in background.

             * @return true if it should
             */
            public boolean getBackgroundData() {
                return getBoolean(SETTING_BACKGROUND_DATA, true);
            }

            /**
             * Convenience function for retrieving a single settings value
             * as a boolean.
             *
             * @param name The name of the setting to retrieve.
             * @param def Value to return if the setting is not defined.
             * @return The setting's current value, or 'def' if it is not defined.
             */
            private boolean getBoolean(String name, boolean def) {
                ContentValues values = getValues(name);
                return values != null ? values.getAsBoolean(VALUE) : def;
            }
        }
    }
}
