/*
 * Copyright (C) 2010 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 com.android.server.content;

import android.accounts.Account;
import android.content.pm.PackageManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;

/**
 * Value type that represents a sync operation.
 * TODO: This is the class to flesh out with all the scheduling data - metered/unmetered,
 * transfer-size, etc.
 * {@hide}
 */
public class SyncOperation implements Comparable {
    public static final String TAG = "SyncManager";

    public static final int REASON_BACKGROUND_DATA_SETTINGS_CHANGED = -1;
    public static final int REASON_ACCOUNTS_UPDATED = -2;
    public static final int REASON_SERVICE_CHANGED = -3;
    public static final int REASON_PERIODIC = -4;
    /** Sync started because it has just been set to isSyncable. */
    public static final int REASON_IS_SYNCABLE = -5;
    /** Sync started because it has just been set to sync automatically. */
    public static final int REASON_SYNC_AUTO = -6;
    /** Sync started because master sync automatically has been set to true. */
    public static final int REASON_MASTER_SYNC_AUTO = -7;
    public static final int REASON_USER_START = -8;

    private static String[] REASON_NAMES = new String[] {
            "DataSettingsChanged",
            "AccountsUpdated",
            "ServiceChanged",
            "Periodic",
            "IsSyncable",
            "AutoSync",
            "MasterSyncAuto",
            "UserStart",
    };

    public static final int SYNC_TARGET_UNKNOWN = 0;
    public static final int SYNC_TARGET_ADAPTER = 1;
    public static final int SYNC_TARGET_SERVICE = 2;

    /** Identifying info for the target for this operation. */
    public final SyncStorageEngine.EndPoint target;
    /** Why this sync was kicked off. {@link #REASON_NAMES} */
    public final int reason;
    /** Where this sync was initiated. */
    public int syncSource;
    public final boolean allowParallelSyncs;
    public Bundle extras;
    public final String key;
    public boolean expedited;
    /** Bare-bones version of this operation that is persisted across reboots. */
    public SyncStorageEngine.PendingOperation pendingOperation;
    /** Elapsed real time in millis at which to run this sync. */
    public long latestRunTime;
    /** Set by the SyncManager in order to delay retries. */
    public Long backoff;
    /** Specified by the adapter to delay subsequent sync operations. */
    public long delayUntil;
    /**
     * Elapsed real time in millis when this sync will be run.
     * Depends on max(backoff, latestRunTime, and delayUntil).
     */
    public long effectiveRunTime;
    /** Amount of time before {@link #effectiveRunTime} from which this sync can run. */
    public long flexTime;

    public SyncOperation(Account account, int userId, int reason, int source, String provider,
            Bundle extras, long runTimeFromNow, long flexTime, long backoff,
            long delayUntil, boolean allowParallelSyncs) {
        this.target = new SyncStorageEngine.EndPoint(account, provider, userId);
        this.reason = reason;
        this.allowParallelSyncs = allowParallelSyncs;
        this.key = initialiseOperation(this.target, source, extras, runTimeFromNow, flexTime,
                backoff, delayUntil);
    }

    public SyncOperation(ComponentName service, int userId, int reason, int source,
            Bundle extras, long runTimeFromNow, long flexTime, long backoff,
            long delayUntil) {
        this.target = new SyncStorageEngine.EndPoint(service, userId);
        // Default to true for sync service. The service itself decides how to handle this.
        this.allowParallelSyncs = true;
        this.reason = reason;
        this.key =
                initialiseOperation(this.target,
                        source, extras, runTimeFromNow, flexTime, backoff, delayUntil);
    }

    /** Used to reschedule a sync at a new point in time. */
    SyncOperation(SyncOperation other, long newRunTimeFromNow) {
        this.target = other.target;
        this.reason = other.reason;
        this.expedited = other.expedited;
        this.allowParallelSyncs = other.allowParallelSyncs;
        // re-use old flex, but only 
        long newFlexTime = Math.min(other.flexTime, newRunTimeFromNow);
        this.key =
                initialiseOperation(this.target,
                    other.syncSource, other.extras,
                    newRunTimeFromNow /* runTimeFromNow*/,
                    newFlexTime /* flexTime */,
                    other.backoff,
                    0L /* delayUntil */);
    }

    private String initialiseOperation(SyncStorageEngine.EndPoint info, int source, Bundle extras,
            long runTimeFromNow, long flexTime, long backoff, long delayUntil) {
        this.syncSource = source;
        this.extras = new Bundle(extras);
        cleanBundle(this.extras);
        this.delayUntil = delayUntil;
        this.backoff = backoff;
        final long now = SystemClock.elapsedRealtime();
        if (runTimeFromNow < 0 || isExpedited()) {
            this.expedited = true;
            this.latestRunTime = now;
            this.flexTime = 0;
        } else {
            this.expedited = false;
            this.latestRunTime = now + runTimeFromNow;
            this.flexTime = flexTime;
        }
        updateEffectiveRunTime();
        return toKey(info, this.extras);
    }

    public boolean matchesAuthority(SyncOperation other) {
        return this.target.matchesSpec(other.target);
    }

    /**
     * Make sure the bundle attached to this SyncOperation doesn't have unnecessary
     * flags set.
     * @param bundle to clean.
     */
    private void cleanBundle(Bundle bundle) {
        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_UPLOAD);
        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_MANUAL);
        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS);
        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF);
        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY);
        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS);
        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_EXPEDITED);
        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS);
        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_DISALLOW_METERED);
    }

    private void removeFalseExtra(Bundle bundle, String extraName) {
        if (!bundle.getBoolean(extraName, false)) {
            bundle.remove(extraName);
        }
    }

    /**
     * Determine whether if this sync operation is running, the provided operation would conflict
     * with it.
     * Parallel syncs allow multiple accounts to be synced at the same time. 
     */
    public boolean isConflict(SyncOperation toRun) {
        final SyncStorageEngine.EndPoint other = toRun.target;
        if (target.target_provider) {
            return target.account.type.equals(other.account.type)
                    && target.provider.equals(other.provider)
                    && target.userId == other.userId
                    && (!allowParallelSyncs
                            || target.account.name.equals(other.account.name));
        } else {
            // Ops that target a service default to allow parallel syncs, which is handled by the
            // service returning SYNC_IN_PROGRESS if they don't.
            return target.service.equals(other.service) && !allowParallelSyncs;
        }
    }

    @Override
    public String toString() {
        return dump(null, true);
    }

    public String dump(PackageManager pm, boolean useOneLine) {
        StringBuilder sb = new StringBuilder();
        if (target.target_provider) {
            sb.append(target.account.name)
                .append(" u")
                .append(target.userId).append(" (")
                .append(target.account.type)
                .append(")")
                .append(", ")
                .append(target.provider)
                .append(", ");
        } else if (target.target_service) {
            sb.append(target.service.getPackageName())
                .append(" u")
                .append(target.userId).append(" (")
                .append(target.service.getClassName()).append(")")
                .append(", ");
        }
        sb.append(SyncStorageEngine.SOURCES[syncSource])
            .append(", currentRunTime ")
            .append(effectiveRunTime);
        if (expedited) {
            sb.append(", EXPEDITED");
        }
        sb.append(", reason: ");
        sb.append(reasonToString(pm, reason));
        if (!useOneLine && !extras.keySet().isEmpty()) {
            sb.append("\n    ");
            extrasToStringBuilder(extras, sb);
        }
        return sb.toString();
    }

    public static String reasonToString(PackageManager pm, int reason) {
        if (reason >= 0) {
            if (pm != null) {
                final String[] packages = pm.getPackagesForUid(reason);
                if (packages != null && packages.length == 1) {
                    return packages[0];
                }
                final String name = pm.getNameForUid(reason);
                if (name != null) {
                    return name;
                }
                return String.valueOf(reason);
            } else {
                return String.valueOf(reason);
            }
        } else {
            final int index = -reason - 1;
            if (index >= REASON_NAMES.length) {
                return String.valueOf(reason);
            } else {
                return REASON_NAMES[index];
            }
        }
    }

    public boolean isInitialization() {
        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false);
    }

    public boolean isExpedited() {
        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false) || expedited;
    }

    public boolean ignoreBackoff() {
        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false);
    }

    public boolean isNotAllowedOnMetered() {
        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, false);
    }

    /** Changed in V3. */
    public static String toKey(SyncStorageEngine.EndPoint info, Bundle extras) {
        StringBuilder sb = new StringBuilder();
        if (info.target_provider) {
            sb.append("provider: ").append(info.provider);
            sb.append(" account {name=" + info.account.name
                    + ", user="
                    + info.userId
                    + ", type="
                    + info.account.type
                    + "}");
        } else if (info.target_service) {
            sb.append("service {package=" )
                .append(info.service.getPackageName())
                .append(" user=")
                .append(info.userId)
                .append(", class=")
                .append(info.service.getClassName())
                .append("}");
        } else {
            Log.v(TAG, "Converting SyncOperaton to key, invalid target: " + info.toString());
            return "";
        }
        sb.append(" extras: ");
        extrasToStringBuilder(extras, sb);
        return sb.toString();
    }

    private static void extrasToStringBuilder(Bundle bundle, StringBuilder sb) {
        sb.append("[");
        for (String key : bundle.keySet()) {
            sb.append(key).append("=").append(bundle.get(key)).append(" ");
        }
        sb.append("]");
    }

    public String wakeLockKey() {
        if (target.target_provider) {
            return target.account.name + "/" + target.account.type + ":" + target.provider;
        } else if (target.target_service) {
            return target.service.getPackageName() + "/" + target.service.getClassName();
        } else {
            Log.wtf(TAG, "Invalid target getting wakelock for operation - " + key);
            return null;
        }
    }

    public String wakeLockName() {
        if (target.target_provider) {
            return "/" + target.provider
                    + "/" + target.account.type
                    + "/" + target.account.name;
        } else if (target.target_service) {
            return "/" + target.service.getPackageName()
                    + "/" + target.service.getClassName();
        } else {
            Log.wtf(TAG, "Invalid target getting wakelock name for operation - " + key);
            return null;
        }
    }

    /**
     * Update the effective run time of this Operation based on latestRunTime (specified at
     * creation time of sync), delayUntil (specified by SyncAdapter), or backoff (specified by
     * SyncManager on soft failures).
     */
    public void updateEffectiveRunTime() {
        // Regardless of whether we're in backoff or honouring a delayUntil, we still incorporate
        // the flex time provided by the developer.
        effectiveRunTime = ignoreBackoff() ?
                latestRunTime :
                    Math.max(Math.max(latestRunTime, delayUntil), backoff);
    }

    /**
     * SyncOperations are sorted based on their earliest effective run time.
     * This comparator is used to sort the SyncOps at a given time when
     * deciding which to run, so earliest run time is the best criteria.
     */
    @Override
    public int compareTo(Object o) {
        SyncOperation other = (SyncOperation) o;
        if (expedited != other.expedited) {
            return expedited ? -1 : 1;
        }
        long thisIntervalStart = Math.max(effectiveRunTime - flexTime, 0);
        long otherIntervalStart = Math.max(
            other.effectiveRunTime - other.flexTime, 0);
        if (thisIntervalStart < otherIntervalStart) {
            return -1;
        } else if (otherIntervalStart < thisIntervalStart) {
            return 1;
        } else {
            return 0;
        }
    }

    // TODO: Test this to make sure that casting to object doesn't lose the type info for EventLog.
    public Object[] toEventLog(int event) {
        Object[] logArray = new Object[4];
        logArray[1] = event;
        logArray[2] = syncSource;
        if (target.target_provider) {
            logArray[0] = target.provider;
            logArray[3] = target.account.name.hashCode();
        } else if (target.target_service) {
            logArray[0] = target.service.getPackageName();
            logArray[3] = target.service.hashCode();
        } else {
            Log.wtf(TAG, "sync op with invalid target: " + key);
        }
        return logArray;
    }
}
