package com.zegoggles.smssync.service;

import android.annotation.TargetApi;
import android.content.Intent;
import android.os.Build;
import android.os.PowerManager;
import android.provider.Telephony;
import android.util.Log;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.internet.BinaryTempFileBody;
import com.squareup.otto.Produce;
import com.squareup.otto.Subscribe;
import com.zegoggles.smssync.App;
import com.zegoggles.smssync.R;
import com.zegoggles.smssync.auth.TokenRefresher;
import com.zegoggles.smssync.mail.MessageConverter;
import com.zegoggles.smssync.mail.PersonLookup;
import com.zegoggles.smssync.preferences.AuthPreferences;
import com.zegoggles.smssync.service.exception.SmsProviderNotWritableException;
import com.zegoggles.smssync.service.state.RestoreState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.io.FilenameFilter;

import static com.zegoggles.smssync.App.LOCAL_LOGV;
import static com.zegoggles.smssync.App.TAG;
import static com.zegoggles.smssync.mail.DataType.CALLLOG;
import static com.zegoggles.smssync.mail.DataType.SMS;
import static com.zegoggles.smssync.service.state.SmsSyncState.ERROR;

public class SmsRestoreService extends ServiceBase {
    private static final int RESTORE_ID = 2;

    @NotNull private RestoreState mState = new RestoreState();
    @Nullable private static SmsRestoreService service;

    @Override @NotNull
    public RestoreState getState() {
        return mState;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        asyncClearCache();
        BinaryTempFileBody.setTempDirectory(getCacheDir());
        service = this;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (LOCAL_LOGV) Log.v(TAG, "SmsRestoreService#onDestroy(state"+getState()+")");
        service = null;
    }

    /**
     * Android KitKat and above require SMS Backup+ to be the default SMS application in order to
     * write to the SMS Provider.
     */
    @TargetApi(Build.VERSION_CODES.KITKAT)
    private boolean canWriteToSmsProvider() {
        return Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT ||
               getPackageName().equals(Telephony.Sms.getDefaultSmsPackage(this));
    }

    @Override
    protected void handleIntent(final Intent intent) {
        if (isWorking()) return;
        if (!canWriteToSmsProvider()) {
            postError(new SmsProviderNotWritableException());
            return;
        }

        try {
            final boolean starredOnly   = getPreferences().isRestoreStarredOnly();
            final boolean restoreCallLog = CALLLOG.isRestoreEnabled(service);
            final boolean restoreSms     = SMS.isRestoreEnabled(service);

            MessageConverter converter = new MessageConverter(service,
                    getPreferences(),
                    getAuthPreferences().getUserEmail(),
                    new PersonLookup(getContentResolver())
            );

            RestoreConfig config = new RestoreConfig(
                getBackupImapStore(),
                0,
                restoreSms,
                restoreCallLog,
                starredOnly,
                getPreferences().getMaxItemsPerRestore(),
                0
            );

            new RestoreTask(this, converter, getContentResolver(),
                    new TokenRefresher(service, new AuthPreferences(this))).execute(config);

        } catch (MessagingException e) {
            postError(e);
        }
    }

    private void postError(Exception exception) {
        App.bus.post(mState.transition(ERROR, exception));
    }

    private void asyncClearCache() {
        new Thread("clearCache") {
            @Override
            public void run() {
                clearCache();
            }
        }.start();
    }

    public synchronized void clearCache() {
        File tmp = getCacheDir();
        if (tmp == null) return; // not sure why this would return null

        Log.d(TAG, "clearing cache in " + tmp);
        for (File f : tmp.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.startsWith("body");
            }
        })) {
            if (LOCAL_LOGV) Log.v(TAG, "deleting " + f);
            if (!f.delete()) Log.w(TAG, "error deleting " + f);
        }
    }

    @Subscribe public void restoreStateChanged(final RestoreState state) {
        mState = state;
        if (mState.isInitialState()) return;

        if (mState.isRunning()) {
            if (notification == null) {
                notification = createNotification(R.string.status_restore);
            }
            notification.setLatestEventInfo(this,
                    getString(R.string.status_restore),
                    state.getNotificationLabel(getResources()),
                    getPendingIntent());

            startForeground(RESTORE_ID, notification);
        } else {
            Log.d(TAG, "stopping service, state"+mState);
            stopForeground(true);
            stopSelf();
        }
    }

    @Produce public RestoreState produceLastState() {
        return mState;
    }

    @Override protected int wakeLockType() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // hold a full wake lock when restoring on newer version of Android, since
            // the user needs to switch  back the sms app afterwards
            return PowerManager.FULL_WAKE_LOCK;
        } else {
            return super.wakeLockType();
        }
    }

    public static boolean isServiceWorking() {
        return service != null && service.isWorking();
    }
}

@@ -2404,235 +2404,98 @@
 rn;%0A
-        if (!canWriteToSmsProvider()) %7B%0A            postError(new SmsProviderNotWritableException());%0A            return;%0A        %7D%0A%0A        try %7B%0A            final boolean starredOnly   = getPreferences().isRestoreStarredOnly(
+%0A        try %7B%0A            final boolean restoreCallLog = CALLLOG.isRestoreEnabled(service
 );%0A 
@@ -2526,33 +2526,29 @@
  restore
-CallLog = CALLLOG
+Sms     = SMS
 .isResto
@@ -2559,32 +2559,33 @@
 abled(service);%0A
+%0A
             fina
@@ -2584,69 +2584,157 @@
     
-final boolean restoreSms     = SMS.isRestoreEnabled(service);
+if (restoreSms && !canWriteToSmsProvider()) %7B%0A                postError(new SmsProviderNotWritableException());%0A                return;%0A            %7D
 %0A%0A  
@@ -3159,17 +3159,43 @@
         
-s
+getPreferences().isRestoreS
 tarredOn
@@ -3196,16 +3196,18 @@
 rredOnly
+()
 ,%0A      

Check if the user actually wants to restore SMS