content: package com.zzzmode.appopsx.ui.main.backup;
  
  import android.app.AppOpsManager;
  import android.content.Context;
  import android.os.Handler;
  import android.os.Looper;
  import android.text.TextUtils;
  import android.widget.Toast;
  import com.zzzmode.appopsx.R;
  import com.zzzmode.appopsx.common.OpsResult;
  import com.zzzmode.appopsx.ui.core.Helper;
  import com.zzzmode.appopsx.ui.model.AppInfo;
  import com.zzzmode.appopsx.ui.model.PreAppInfo;
  import io.reactivex.Observable;
  import io.reactivex.ObservableSource;
  import io.reactivex.SingleObserver;
  import io.reactivex.android.schedulers.AndroidSchedulers;
  import io.reactivex.annotations.NonNull;
  import io.reactivex.disposables.Disposable;
  import io.reactivex.functions.BiConsumer;
  import io.reactivex.functions.Consumer;
  import io.reactivex.functions.Function;
  import io.reactivex.observers.ResourceObserver;
  import io.reactivex.schedulers.Schedulers;
  import java.io.File;
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.Comparator;
  import java.util.List;
  import java.util.concurrent.Callable;
  import java.util.concurrent.atomic.AtomicInteger;
  import org.json.JSONArray;
  import org.json.JSONObject;
  
  /**
   * Created by zl on 2017/5/7.
   */
  
  class ConfigPresenter {
  
    private static final String TAG = "ConfigPresenter";
  
    private IConfigView mView;
  
    private Context context;
  
    ConfigPresenter(Context context, IConfigView view) {
      this.mView = view;
      this.context = context;
    }
  
  
    void export(AppInfo[] appInfos) {
      final int max = appInfos.length;
  
      final AtomicInteger progress = new AtomicInteger();
      mView.showProgress(true, max);
      Helper.getAppsPermission(context, appInfos)
          .observeOn(AndroidSchedulers.mainThread())
          .doOnNext(new Consumer<PreAppInfo>() {
            @Override
            public void accept(@NonNull PreAppInfo appInfo) throws Exception {
              mView.setProgress(progress.incrementAndGet());
            }
          })
          .collect(new Callable<List<PreAppInfo>>() {
            @Override
            public List<PreAppInfo> call() throws Exception {
              return new ArrayList<PreAppInfo>();
            }
          }, new BiConsumer<List<PreAppInfo>, PreAppInfo>() {
            @Override
            public void accept(List<PreAppInfo> preAppInfos, PreAppInfo appInfo) throws Exception {
              preAppInfos.add(appInfo);
            }
          }).observeOn(Schedulers.io()).doAfterSuccess(new Consumer<List<PreAppInfo>>() {
        @Override
        public void accept(@NonNull List<PreAppInfo> preAppInfos) throws Exception {
          save2Local(preAppInfos);
        }
      }).observeOn(AndroidSchedulers.mainThread()).subscribe(new SingleObserver<List<PreAppInfo>>() {
  
  
        @Override
        public void onSubscribe(@NonNull Disposable d) {
  
        }
  
        @Override
        public void onSuccess(@NonNull List<PreAppInfo> preAppInfos) {
          mView.showProgress(false, 0);
        }
  
        @Override
        public void onError(@NonNull Throwable e) {
          mView.showProgress(false, 0);
        }
      });
    }
  
    private void save2Local(List<PreAppInfo> preAppInfos) {
      //io thread
  
      final StringBuilder msg = new StringBuilder();
      try {
        JSONObject jsonObject = new JSONObject();
        jsonObject.putOpt("time", System.currentTimeMillis());
        jsonObject.putOpt("v", 1);
        jsonObject.putOpt("size", preAppInfos.size());
        JSONArray jsonArray = new JSONArray();
        for (PreAppInfo preAppInfo : preAppInfos) {
          String ignoredOps = preAppInfo.getIgnoredOps();
          if (!TextUtils.isEmpty(ignoredOps)) {
            JSONObject object = new JSONObject();
            object.putOpt("pkg", preAppInfo.getPackageName());
            object.putOpt("ops", ignoredOps);
            jsonArray.put(object);
          }
        }
        jsonObject.putOpt("opbacks", jsonArray);
        File file = BFileUtils.saveBackup(context, jsonObject.toString());
        msg.append(context.getString(R.string.backup_success, file.getAbsoluteFile()));
      } catch (Exception e) {
        e.printStackTrace();
        msg.append("error").append(e.getMessage());
      }
      Handler handler = new Handler(Looper.getMainLooper());
      handler.post(new Runnable() {
        @Override
        public void run() {
          if (context != null) {
            Toast.makeText(context, msg.toString(), Toast.LENGTH_LONG).show();
          }
        }
      });
    }
  
    List<RestoreModel> getRestoreFiles() {
      List<File> backFiles = BFileUtils.getBackFiles(context);
      if (backFiles != null && !backFiles.isEmpty()) {
        List<RestoreModel> models = new ArrayList<>();
        for (File backFile : backFiles) {
          RestoreModel model = readModel(backFile);
          if (model != null) {
            models.add(model);
          }
        }
  
        Collections.sort(models, new Comparator<RestoreModel>() {
          @Override
          public int compare(RestoreModel o1, RestoreModel o2) {
            return (o1.createTime < o2.createTime) ? 1 : ((o1.createTime == o2.createTime) ? 0 : -1);
          }
        });
  
        return models;
      }
      return null;
    }
  
    void importBack(File file) {
      String s = BFileUtils.read2String(file);
      try {
        JSONObject jsonObject = new JSONObject(s);
        long time = jsonObject.optLong("time");
        int v = jsonObject.optInt("v");
        int size = jsonObject.optInt("size");
        JSONArray jsonArray = jsonObject.optJSONArray("opbacks");
        if (jsonArray != null && jsonArray.length() > 0) {
          int len = jsonArray.length();
          List<PreAppInfo> preAppInfos = new ArrayList<>(len);
          for (int i = 0; i < len; i++) {
            JSONObject jo = jsonArray.optJSONObject(i);
            if (jo != null) {
              String pkg = jo.optString("pkg");
              String ops = jo.optString("ops");
              if (!TextUtils.isEmpty(pkg) && !TextUtils.isEmpty(ops)) {
                preAppInfos.add(new PreAppInfo(pkg, ops));
              }
            }
          }
          //restoreOps(preAppInfos);
        }
      } catch (Exception e) {
        Toast.makeText(context, R.string.backup_file_lack, Toast.LENGTH_LONG).show();
      }
    }
  
  
    private RestoreModel readModel(File file) {
      try {
        RestoreModel model = new RestoreModel();
        model.path = file.getAbsolutePath();
        model.fileName = file.getName();
        model.fileSize = file.length();
  
        String s = BFileUtils.read2String(file);
        JSONObject jsonObject = new JSONObject(s);
        model.createTime = jsonObject.optLong("time");
        model.version = jsonObject.optInt("v");
        model.size = jsonObject.optInt("size");
        JSONArray jsonArray = jsonObject.optJSONArray("opbacks");
        if (jsonArray != null && jsonArray.length() > 0) {
          int len = jsonArray.length();
          List<PreAppInfo> preAppInfos = new ArrayList<>(len);
          for (int i = 0; i < len; i++) {
            JSONObject jo = jsonArray.optJSONObject(i);
            if (jo != null) {
              String pkg = jo.optString("pkg");
              String ops = jo.optString("ops");
              if (!TextUtils.isEmpty(pkg) && !TextUtils.isEmpty(ops)) {
                preAppInfos.add(new PreAppInfo(pkg, ops));
              }
            }
          }
          model.preAppInfos = preAppInfos;
  
          return model;
        }
      } catch (Exception e) {
        if (file != null) {
          file.delete();
        }
      }
      return null;
    }
  
    void restoreOps(final RestoreModel model) {
      final int size = model.preAppInfos.size();
      final AtomicInteger progress = new AtomicInteger();
      mView.showProgress(true, size);
  
      Observable.fromIterable(model.preAppInfos)
          .flatMap(new Function<PreAppInfo, ObservableSource<OpsResult>>() {
            @Override
            public ObservableSource<OpsResult> apply(@NonNull PreAppInfo appInfo) throws Exception {
              return Helper.setModes(context, appInfo.getPackageName(), AppOpsManager.MODE_IGNORED,
                  appInfo.getOps());
            }
          }).subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread()).subscribe(new ResourceObserver<OpsResult>() {
        @Override
        public void onNext(@NonNull OpsResult opsResult) {
          mView.setProgress(progress.incrementAndGet());
        }
  
        @Override
        public void onError(@NonNull Throwable e) {
          progress.incrementAndGet();
        }
  
        @Override
        public void onComplete() {
          mView.showProgress(false, 0);
          Toast.makeText(context, "恢复成功", Toast.LENGTH_LONG).show();
        }
      });
    }
  
  
  }
  