/*
 * Copyright 2016 Peter Kenji Yamanaka
 *
 * 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.pyamsoft.powermanager.dagger.modifier.state;

import android.content.Context;
import android.net.ConnectivityManager;
import android.os.Build;
import android.support.annotation.CheckResult;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.birbit.android.jobqueue.Job;
import java.lang.reflect.Method;
import javax.inject.Inject;
import timber.log.Timber;

public class DataStateModifier extends StateModifier {

  @NonNull private static final String SET_METHOD_NAME = "setMobileDataEnabled";
  @Nullable private static final Method SET_MOBILE_DATA_ENABLED_METHOD;

  static {
    SET_MOBILE_DATA_ENABLED_METHOD = reflectSetMethod();
  }

  @NonNull private final ConnectivityManager connectivityManager;

  @Inject DataStateModifier(@NonNull Context context) {
    super(context);
    connectivityManager = (ConnectivityManager) context.getApplicationContext()
        .getSystemService(Context.CONNECTIVITY_SERVICE);
  }

  @CheckResult @Nullable private static String resolveSetMethodName() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
      return SET_METHOD_NAME;
    } else {
      return null;
    }
  }

  @CheckResult @Nullable private static Method reflectSetMethod() {
    final String setMethodName = resolveSetMethodName();
    if (setMethodName != null) {
      synchronized (Job.class) {
        try {
          final Method method =
              ConnectivityManager.class.getDeclaredMethod(setMethodName, Boolean.TYPE);
          method.setAccessible(true);
          return method;
        } catch (final Exception e) {
          Timber.e(e, "ManagerData reflectSetMethod ERROR");
        }
      }
    }

    Timber.e("Unable to resolve setMobileDataEnabled using reflection");
    return null;
  }

  private static void setMobileDataEnabled(@NonNull ConnectivityManager connectivityManager,
      boolean enabled) {
    if (SET_MOBILE_DATA_ENABLED_METHOD != null) {
      synchronized (Job.class) {
        try {
          Timber.d("setMobileDataEnabled: %s", enabled);
          SET_MOBILE_DATA_ENABLED_METHOD.invoke(connectivityManager, enabled);
        } catch (final Exception e) {
          Timber.e(e, "ManagerData setMobileDataEnabled ERROR");
        }
      }
    }
  }

  @Override void mainThreadSet() {
    setMobileDataEnabled(connectivityManager, true);
  }

  @Override void mainThreadUnset() {
    setMobileDataEnabled(connectivityManager, false);
  }
}

@@ -891,48 +891,8 @@
 le;%0A
-import com.birbit.android.jobqueue.Job;%0A
 impo
@@ -1587,386 +1587,46 @@
 tic 
-String resolveSetMethodName() %7B%0A    if (Build.VERSION.SDK_INT %3C Build.VERSION_CODES.LOLLIPOP) %7B%0A      return SET_METHOD_NAME;%0A    %7D else %7B%0A      return null;%0A    %7D%0A  %7D%0A%0A  @CheckResult @Nullable private static Method reflectSetMethod() %7B%0A    final String setMethodName = resolveSetMethodName();%0A    if (setMethodName != null) %7B%0A      synchronized (Job.class) %7B%0A        try %7B%0A    
+Method reflectSetMethod() %7B%0A    try %7B%0A
     
@@ -1649,20 +1649,16 @@
 ethod =%0A
-    
         
@@ -1707,21 +1707,23 @@
 hod(
-setMethodName
+SET_METHOD_NAME
 , Bo
@@ -1735,20 +1735,16 @@
 .TYPE);%0A
-    
       me
@@ -1775,20 +1775,16 @@
 ;%0A      
-   
- 
 return m
@@ -1790,20 +1790,16 @@
 method;%0A
-    
     %7D ca
@@ -1822,36 +1822,32 @@
 tion e) %7B%0A      
- 
-   
 Timber.e(e, %22Man
@@ -1891,104 +1891,8 @@
     
-  %7D%0A      %7D%0A    %7D%0A%0A    Timber.e(%22Unable to resolve setMobileDataEnabled using reflection%22);%0A    
 retu
@@ -1899,16 +1899,22 @@
 rn null;
+%0A    %7D
 %0A  %7D%0A%0A  
@@ -1921,23 +1921,16 @@
 private 
-static 
 void set
@@ -1950,65 +1950,19 @@
 bled
-(@NonNull ConnectivityManager connectivityManager,%0A      
+Reflection(
 bool
@@ -2030,43 +2030,8 @@
 ) %7B%0A
-      synchronized (Job.class) %7B%0A  
     
@@ -2034,26 +2034,24 @@
       try %7B%0A
-  
         Timb
@@ -2101,18 +2101,16 @@
         
-  
 SET_MOBI
@@ -2176,18 +2176,16 @@
 ;%0A      
-  
 %7D catch 
@@ -2202,26 +2202,24 @@
 eption e) %7B%0A
-  
         Timb
@@ -2273,24 +2273,28 @@
 %22);%0A    
+  %7D%0A
     %7D%0A  
     %7D%0A  
@@ -2285,21 +2285,184 @@
     %7D%0A  
-    %7D
+%7D%0A%0A  private void setMobileDataEnabled(boolean enabled) %7B%0A    if (Build.VERSION.SDK_INT %3C Build.VERSION_CODES.LOLLIPOP) %7B%0A      setMobileDataEnabledReflection(enabled);
 %0A    %7D%0A 
@@ -2525,37 +2525,16 @@
 Enabled(
-connectivityManager, 
 true);%0A 
@@ -2599,37 +2599,16 @@
 Enabled(
-connectivityManager, 
 false);%0A

Clean up mobile data state modifier