/*
 * Copyright 2012-2014 One Platform Foundation
 *
 * 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 org.onepf.opfpush.util;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.PatternMatcher;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import org.onepf.opfpush.PackageChangeReceiver;
import org.onepf.opfpush.PushProvider;
import org.onepf.opfutils.OPFLog;
import org.onepf.opfutils.OPFUtils;

import java.util.List;

import static android.content.pm.PackageManager.GET_RESOLVED_FILTER;
import static org.onepf.opfpush.OPFConstants.ACTION_NO_AVAILABLE_PROVIDER;
import static org.onepf.opfpush.OPFConstants.ACTION_RECEIVE;
import static org.onepf.opfpush.OPFConstants.ACTION_REGISTRATION;
import static org.onepf.opfpush.OPFConstants.ACTION_UNREGISTRATION;

/**
 * @author Kirill Rozov
 * @author Roman Savin
 * @since 07.09.14
 */
public final class ReceiverUtils {

    private static final String PACKAGE_DATA_SCHEME = "package";

    private ReceiverUtils() {
        throw new UnsupportedOperationException();
    }

    public static BroadcastReceiver registerPackageChangeReceiver(
            @NonNull final Context context,
            @NonNull final PushProvider provider
    ) {
        OPFLog.methodD(context, provider);

        final PackageChangeReceiver packageChangeReceiver = new PackageChangeReceiver(provider);

        final IntentFilter appUpdateFilter = new IntentFilter(Intent.ACTION_PACKAGE_REPLACED);
        appUpdateFilter.addDataScheme(ReceiverUtils.PACKAGE_DATA_SCHEME);
        appUpdateFilter.addDataPath(context.getPackageName(), PatternMatcher.PATTERN_LITERAL);
        context.registerReceiver(packageChangeReceiver, appUpdateFilter);

        final String hostAppPackage = provider.getHostAppPackage();
        if (hostAppPackage != null) {
            OPFLog.d("Host app package isn't null");

            final IntentFilter hostAppRemovedFilter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
            hostAppRemovedFilter.addDataScheme(ReceiverUtils.PACKAGE_DATA_SCHEME);
            hostAppRemovedFilter.addDataPath(hostAppPackage, PatternMatcher.PATTERN_LITERAL);
            context.registerReceiver(packageChangeReceiver, hostAppRemovedFilter);
        }

        return packageChangeReceiver;
    }

    public static boolean isOPFReceiverRegistered(@NonNull final Context context) {
        OPFLog.methodD(context);

        final Intent intent = new Intent(ACTION_RECEIVE);
        final List<ResolveInfo> resolveInfos = context.getPackageManager()
                .queryBroadcastReceivers(intent, GET_RESOLVED_FILTER);

        for (ResolveInfo resolveInfo : resolveInfos) {
            final IntentFilter intentFilter = resolveInfo.filter;
            if (intentFilter != null && intentFilter.hasAction(ACTION_RECEIVE)
                    && intentFilter.hasAction(ACTION_REGISTRATION)
                    && intentFilter.hasAction(ACTION_UNREGISTRATION)
                    && intentFilter.hasAction(ACTION_NO_AVAILABLE_PROVIDER)) {
                return true;
            }
        }

        return false;
    }

    public static void checkReceiver(@NonNull final Context context,
                                     @NonNull final Intent broadcastIntent,
                                     @NonNull final String receiverName,
                                     @Nullable final String permission) {
        final PackageManager packageManager = context.getPackageManager();
        final String packageName = context.getPackageName();

        final List<ResolveInfo> receivers = packageManager
                .queryBroadcastReceivers(broadcastIntent, PackageManager.GET_INTENT_FILTERS);
        if (receivers.isEmpty()) {
            throw new IllegalStateException("No receivers for intent "
                    + OPFUtils.toString(broadcastIntent));
        }

        ResolveInfo neededReceiver = null;
        for (ResolveInfo receiver : receivers) {
            if (receiver.activityInfo.name.equals(receiverName)
                    && receiver.activityInfo.packageName.equals(packageName)) {
                neededReceiver = receiver;
                break;
            }
        }

        if (neededReceiver == null) {
            throw new IllegalStateException("Receiver " + receiverName
                    + " hasn't been declared in AndroidManifest.xml");
        }

        if (permission != null
                && !permission.equals(neededReceiver.activityInfo.permission)) {
            throw new IllegalStateException("There is no permission "
                    + permission
                    + " for receiver "
                    + receiverName);
        }
    }
}

@@ -1170,77 +1170,8 @@
 t;%0A%0A
-import static android.content.pm.PackageManager.GET_RESOLVED_FILTER;%0A
 impo
@@ -3046,17 +3046,16 @@
 ntext);%0A
-%0A
         
@@ -3073,16 +3073,32 @@
 t intent
+BroadcastReceive
  = new I
@@ -3138,141 +3138,78 @@
 nal 
-List%3CResolveInfo%3E resolveInfos = context.getPackageManager()%0A                .queryBroadcastReceivers(intent, GET_RESOLVED_FILTER
+Intent intentBroadcastRegistration = new Intent(ACTION_REGISTRATION
 );%0A
-%0A
     
@@ -3217,53 +3217,86 @@
    f
-or (ResolveInfo resolveInfo : resolveInfos) %7B
+inal Intent intentBroadcastUnregistration = new Intent(ACTION_UNREGISTRATION);
 %0A   
@@ -3292,36 +3292,32 @@
 ATION);%0A        
-    
 final IntentFilt
@@ -3316,128 +3316,88 @@
 tent
-Filter
  intent
-Filter = resolveInfo.filter;%0A            if (intentFilt
+BroadcastNoAvailableProvid
 er 
-!
 = n
-ull && intentFilter.hasAction(ACTION_RECEIVE)
+ew Intent(ACTION_NO_AVAILABLE_PROVIDER);%0A
 %0A   
@@ -3393,33 +3393,38 @@
 IDER);%0A%0A        
- 
+try %7B%0A
            && in
@@ -3422,245 +3422,373 @@
     
-&& intentFilter.hasAction(ACTION_REGISTRATION)%0A                    && intentFilter.hasAction(ACTION_UNREGISTRATION)%0A                    && intentFilter.hasAction(ACTION_NO_AVAILABLE_PROVIDER)) %7B%0A                return true;%0A            %7D
+ checkReceiver(context, intentBroadcastReceive, null, null);%0A            checkReceiver(context, intentBroadcastRegistration, null, null);%0A            checkReceiver(context, intentBroadcastUnregistration, null, null);%0A            checkReceiver(context, intentBroadcastNoAvailableProvider, null, null);%0A        %7D catch (RuntimeException e) %7B%0A            return false;
 %0A   
@@ -3786,33 +3786,32 @@
 alse;%0A        %7D%0A
-%0A
         return f
@@ -3805,28 +3805,27 @@
      return 
-fals
+tru
 e;%0A    %7D%0A%0A  
@@ -4002,30 +4002,31 @@
           @N
-onN
 ull
+able
  final Strin
@@ -4681,32 +4681,57 @@
             if (
+(receiverName == null %7C%7C 
 receiver.activit
@@ -4761,16 +4761,17 @@
 verName)
+)
 %0A       

Fix bug with OPFPushReceiver.