package org.commcare.provider;

import android.content.Intent;
import android.support.annotation.NonNull;
import android.util.Base64;
import android.util.Log;

import com.simprints.libsimprints.Constants;
import com.simprints.libsimprints.FingerIdentifier;
import com.simprints.libsimprints.Identification;
import com.simprints.libsimprints.Registration;
import com.simprints.libsimprints.Tier;

import org.javarosa.core.model.FormDef;
import org.javarosa.core.model.condition.EvaluationContext;
import org.javarosa.core.model.instance.AbstractTreeElement;
import org.javarosa.core.model.instance.TreeReference;
import org.javarosa.core.services.locale.Localization;
import org.javarosa.core.util.OrderedHashtable;
import org.commcare.android.javarosa.IntentCallout;

import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;

/**
 * Process simprints fingerprint registration and identification callout results.
 *
 * @author Phillip Mates (pmates@dimagi.com).
 */
public class SimprintsCalloutProcessing {
    private static final String TAG = SimprintsCalloutProcessing.class.getSimpleName();

    /**
     * Fingerprint lookup response from Simprints scanner app.
     * Idenficiation responses contain a list of top matching Case IDs with an
     * associated confidence score.
     */
    public static boolean isIdentificationResponse(Intent intent) {
        return intent.hasExtra(Constants.SIMPRINTS_IDENTIFICATIONS);
    }

    /**
     * Fingerprint registration response from Simprints scanner app.
     * Registration responses contain fingerprint templates for the scanned fingerprints
     */
    public static boolean isRegistrationResponse(Intent intent) {
        return intent.hasExtra(Constants.SIMPRINTS_REGISTRATION);
    }

    public static OrderedHashtable<String, String> getConfidenceMatchesFromCalloutResponse(Intent intent) {
        List<Identification> idReadings = (List)intent.getParcelableArrayListExtra(Constants.SIMPRINTS_IDENTIFICATIONS);

        Collections.sort(idReadings);

        OrderedHashtable<String, String> guidToConfidenceMap = new OrderedHashtable<>();
        for (Identification id : idReadings) {
            guidToConfidenceMap.put(id.getGuid(), getTierText(id.getTier()));
        }

        return guidToConfidenceMap;
    }

    private static String getTierText(@NonNull Tier tier) {
        switch (tier) {
            case TIER_1:
                return Localization.get("fingerprint.match.100");
            case TIER_2:
                return Localization.get("fingerprint.match.75");
            case TIER_3:
                return Localization.get("fingerprint.match.50");
            case TIER_4:
                return Localization.get("fingerprint.match.25");
            case TIER_5:
                return Localization.get("fingerprint.match.0");
            default:
                return Localization.get("fingerprint.match.unknown");
        }
    }

    private static Registration getRegistrationData(Intent intent) {
        return intent.getParcelableExtra(Constants.SIMPRINTS_REGISTRATION);
    }

    public static boolean processRegistrationResponse(FormDef formDef, Intent intent, TreeReference intentQuestionRef,
                                                      Hashtable<String, Vector<TreeReference>> responseToRefMap) {
        Registration registration = getRegistrationData(intent);

        // Store all the fingerprint responses
        int numOfFingersScanned = 0;
        for (FingerIdentifier fingerIdentifier : FingerIdentifier.values()) {
            Vector<TreeReference> fingerRefs =  responseToRefMap.get(fingerIdentifier.toString());
            if (fingerRefs != null && !fingerRefs.isEmpty()) {
                byte[] template = registration.getTemplate(fingerIdentifier);
                storeValueFromRegistrationResponse(formDef, fingerRefs, intentQuestionRef,
                        Base64.encodeToString(template, Base64.DEFAULT));
                numOfFingersScanned += countTemplateScanned(template);
            }
        }

        // Store the guid response
        String guid = registration.getGuid();
        Vector<TreeReference> refsToStoreGuidAt = responseToRefMap.get("guid");
        if (refsToStoreGuidAt != null && guid != null) {
            storeValueFromRegistrationResponse(formDef, refsToStoreGuidAt, intentQuestionRef, guid);
        }

        String resultMessage =
                Localization.get("fingerprints.scanned", new String[]{"" + numOfFingersScanned});
        IntentCallout.setNodeValue(formDef, intentQuestionRef, resultMessage);

        return (numOfFingersScanned > 0);
    }

    private static int countTemplateScanned(byte[] template) {
        return (template == null || template.length == 0) ? 0 : 1;
    }

    private static void storeValueFromRegistrationResponse(FormDef formDef,
                                                           Vector<TreeReference> treeRefs,
                                                           TreeReference contextRef,
                                                           String responseValue) {
        for (TreeReference ref : treeRefs) {
            storeValueFromRegistrationResponse(formDef, ref, contextRef, responseValue);
        }
    }

    private static void storeValueFromRegistrationResponse(FormDef formDef, TreeReference ref,
                                                           TreeReference contextRef,
                                                           String responseValue) {
        EvaluationContext context = new EvaluationContext(formDef.getEvaluationContext(), contextRef);
        TreeReference fullRef = ref.contextualize(contextRef);
        AbstractTreeElement node = context.resolveReference(fullRef);

        if (node == null) {
            Log.e(TAG, "Unable to resolve ref " + ref);
            return;
        }
        int dataType = node.getDataType();

        IntentCallout.setValueInFormDef(formDef, fullRef, responseValue, dataType);
    }
}

@@ -4637,17 +4637,32 @@
  return 
-(
+guid != null %7C%7C 
 numOfFin
@@ -4676,17 +4676,16 @@
 nned %3E 0
-)
 ;%0A    %7D%0A

change definition of successful Simprints callout processing