package nordpol.android;

import android.nfc.Tag;
import android.nfc.NfcAdapter;
import android.nfc.tech.IsoDep;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;

public class TagDispatcher {
    private OnDiscoveredTagListener listener;
    private Activity activity;
    private NfcAdapter adapter;

    private TagDispatcher(Activity activity, NfcAdapter adapter,
                          OnDiscoveredTagListener listener) {
        this.activity = activity;
        this.adapter = adapter;
        this.listener = listener;
    }

    public static TagDispatcher get(Activity activity, NfcAdapter adapter,
                                    OnDiscoveredTagListener listener) {
        return new TagDispatcher(activity, adapter, listener);
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    public void enableExclusiveNfc() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            enableReaderMode();
        } else {
            enableForegroundDispatch();
        }
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    public void disableExclusiveNfc() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            disableReaderMode();
        } else {
            disableForegroundDispatch();
        }
    }

    public boolean interceptIntent(Intent intent) {
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if(tag != null) {
            listener.tagDiscovered(tag);
            return true;
        } else {
            return false;
        }
    }

    private void enableReaderMode() {
        Bundle options = new Bundle();
        /* This is a work around for some Broadcom chipsets that does
         * the presence check by sending commands that interrupt the
         * processing of the ongoing command.
         */
        options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 5000);
        NfcAdapter.ReaderCallback callback = new NfcAdapter.ReaderCallback() {
                public void onTagDiscovered(Tag tag) {
                    listener.tagDiscovered(tag);
                }
            };
        adapter.enableReaderMode(activity,
                                 callback,
                                 NfcAdapter.FLAG_READER_NFC_A |
                                 NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK |
                                 NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS,
                                 options);
    }

    private void disableReaderMode() {
        adapter.disableReaderMode(activity);
    }

    private void enableForegroundDispatch() {
        // activity.getIntent() can not be use due to issues with pending intents containg extras of custom classes (https://code.google.com/p/android/issues/detail?id=6822)
        Intent intent = new Intent(activity, activity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        enableForegroundDispatch(intent);
    }

    private void enableForegroundDispatch(Intent intent) {
        if(adapter.isEnabled()) {
            PendingIntent tagIntent = PendingIntent.getActivity(activity, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
            IntentFilter tag = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);

            adapter.enableForegroundDispatch(activity, tagIntent, new IntentFilter[]{tag},
                                             new String[][]{new String[]{IsoDep.class.getName()}});
        }
    }

    private void disableForegroundDispatch() {
        adapter.disableForegroundDispatch(activity);
    }

}

@@ -435,40 +435,8 @@
 ity;
-%0A    private NfcAdapter adapter;
 %0A%0A  
@@ -477,36 +477,16 @@
 ctivity,
- NfcAdapter adapter,
 %0A       
@@ -578,40 +578,8 @@
 ty;%0A
-        this.adapter = adapter;%0A
     
@@ -673,28 +673,8 @@
 ity,
- NfcAdapter adapter,
 %0A   
@@ -788,17 +788,8 @@
 ity,
- adapter,
  lis
@@ -877,32 +877,136 @@
 xclusiveNfc() %7B%0A
+        NfcAdapter adapter = NfcAdapter.getDefaultAdapter(activity);%0A        if (adapter != null) %7B%0A    
         if (Buil
@@ -1048,32 +1048,36 @@
 CODES.KITKAT) %7B%0A
+    
             enab
@@ -1081,32 +1081,39 @@
 nableReaderMode(
+adapter
 );%0A        %7D els
@@ -1099,32 +1099,36 @@
 apter);%0A        
+  
+  
 %7D else %7B%0A       
@@ -1112,32 +1112,36 @@
        %7D else %7B%0A
+    
             enab
@@ -1153,34 +1153,55 @@
 egroundDispatch(
-);
+adapter);%0A            %7D
 %0A        %7D%0A    %7D
@@ -1277,32 +1277,136 @@
 xclusiveNfc() %7B%0A
+        NfcAdapter adapter = NfcAdapter.getDefaultAdapter(activity);%0A        if (adapter != null) %7B%0A    
         if (Buil
@@ -1448,32 +1448,36 @@
 CODES.KITKAT) %7B%0A
+    
             disa
@@ -1490,16 +1490,23 @@
 derMode(
+adapter
 );%0A     
@@ -1500,32 +1500,36 @@
 apter);%0A        
+ 
+   
 %7D else %7B%0A       
@@ -1513,32 +1513,36 @@
        %7D else %7B%0A
+    
             disa
@@ -1563,18 +1563,39 @@
 ispatch(
-);
+adapter);%0A            %7D
 %0A       
@@ -1901,32 +1901,50 @@
 nableReaderMode(
+NfcAdapter adapter
 ) %7B%0A        Bund
@@ -2844,16 +2844,34 @@
 derMode(
+NfcAdapter adapter
 ) %7B%0A    
@@ -2952,32 +2952,50 @@
 egroundDispatch(
+NfcAdapter adapter
 ) %7B%0A        // a
@@ -3298,16 +3298,25 @@
 ispatch(
+adapter, 
 intent);
@@ -3365,16 +3365,36 @@
 ispatch(
+NfcAdapter adapter, 
 Intent i
@@ -3893,16 +3893,34 @@
 ispatch(
+NfcAdapter adapter
 ) %7B%0A    

Embed NfcAdapter handling into TagDispatcher