﻿B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=Class
Version=12.8
@EndOfDesignText@
'version: 1.00
Sub Class_Globals
	Public Const FORMAT_ALL_FORMATS = 0, FORMAT_AZTEC = 4096, FORMAT_CODABAR = 8, FORMAT_CODE_128 = 1, FORMAT_CODE_39 = 2, FORMAT_CODE_93 = 4 As Int
	Public Const FORMAT_DATA_MATRIX = 16, FORMAT_EAN_13 = 32, FORMAT_EAN_8 = 64, FORMAT_ITF = 128, FORMAT_PDF417 = 2048, FORMAT_QR_CODE = 256 As Int
	Public Const FORMAT_UPC_A = 512, FORMAT_UPC_E = 1024 As Int
	Type ScannerResult (Success As Boolean, Value As String, Barcode As JavaObject)
End Sub

'Initializes the object.
Public Sub Initialize
	Dim m As JavaObject
	m = Me
	Dim eventName As String = "gcs"
	m.RunMethod("checkModuleIntalled", Array(eventName))
End Sub

Public Sub Scan (Formats As List) As ResumableSub
	Try
		Dim builder As JavaObject
		builder.InitializeNewInstance("com/google/mlkit/vision/codescanner/GmsBarcodeScannerOptions.Builder".Replace("/", "."), Null)
		Dim f(Formats.Size - 1) As Int
		For i = 1 To Formats.Size - 1
			f(i - 1) = Formats.Get(i)
		Next
		builder.RunMethod("setBarcodeFormats", Array(Formats.Get(0), f))
		builder.RunMethod("enableAutoZoom", Null)
		Dim options As JavaObject = builder.RunMethod("build", Null)
		Dim scanning As JavaObject
		Dim ctxt As JavaObject
		ctxt.InitializeContext
		Dim scanner As JavaObject = scanning.InitializeStatic("com/google/mlkit/vision/codescanner/GmsBarcodeScanning".Replace("/", ".")).RunMethod("getClient", Array(ctxt, options))
		Dim o As JavaObject = scanner.RunMethod("startScan", Null)
		Do While o.RunMethod("isComplete", Null).As(Boolean) = False
			Sleep(50)
		Loop
		Dim res As ScannerResult
		res.Initialize
		If o.RunMethod("isSuccessful", Null) Then
			res.Success = True
			res.Barcode = o.RunMethod("getResult", Null)
			res.Value = res.Barcode.RunMethod("getRawValue", Null)
		Else
			Log("error: " & o.RunMethod("getException", Null))
		End If
		Return res
	Catch
		Log(LastException)
	End Try

	Dim res As ScannerResult
	res.Initialize
	res.Success = False
	res.Value = "ERROR"
	Return res
End Sub

Public Sub gcs_module_installed(installed As String)
	Log("Back in B4A : " & installed)
End Sub

Public Sub gcs_modules_present_on_device(present As String)
	Log("Back in B4A : " & present)
End Sub

#If Java

import com.google.android.gms.common.moduleinstall.InstallStatusListener;
import com.google.android.gms.common.moduleinstall.ModuleInstallStatusUpdate;
import com.google.android.gms.common.moduleinstall.ModuleInstallClient;
import com.google.android.gms.common.moduleinstall.ModuleInstall;
import com.google.android.gms.common.moduleinstall.ModuleInstallRequest;
import com.google.android.gms.common.moduleinstall.ModuleInstallResponse;
import com.google.android.gms.common.moduleinstall.ModuleAvailabilityResponse;
import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions;
import com.google.mlkit.vision.codescanner.GmsBarcodeScanning;
import com.google.mlkit.vision.codescanner.GmsBarcodeScanner;
import com.google.android.gms.common.api.OptionalModuleApi;

import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.Events;

import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;

import androidx.annotation.NonNull;

ModuleInstallClient moduleInstallClient;

private BA ba;
private String eventName = "";

public void checkModuleIntalled(String eventName) {
	this.eventName = eventName;

	// ✅ Correctly assign to the class field, NOT a local variable
	moduleInstallClient = ModuleInstall.getClient(ba.applicationContext);

	OptionalModuleApi optionalModuleApi = GmsBarcodeScanning.getClient(ba.applicationContext);

	moduleInstallClient
		.areModulesAvailable(optionalModuleApi)
		.addOnSuccessListener(new OnSuccessListener<ModuleAvailabilityResponse>() {
			@Override
			public void onSuccess(@NonNull ModuleAvailabilityResponse response) {
				if (response.areModulesAvailable()) {
					if (ba.subExists(eventName + "_modules_present_on_device")) {
						ba.raiseEvent2(ba, false, eventName + "_modules_present_on_device", true, new Object[]{"Modules are present on the device"});
					}
				} else {
					BA.Log("Modules are not present. Starting install.");
					moduleInstall();
				}
			}
		})
		.addOnFailureListener(new OnFailureListener() {
			@Override
			public void onFailure(@NonNull Exception e) {
				BA.Log("ERROR = " + e);
			}
		});
}

final class ModuleInstallProgressListener implements InstallStatusListener {
	@Override
	public void onInstallStatusUpdated(ModuleInstallStatusUpdate update) {
		ModuleInstallStatusUpdate.ProgressInfo progressInfo = update.getProgressInfo();
		if (progressInfo != null) {
			int progress = (int) (progressInfo.getBytesDownloaded() * 100 / progressInfo.getTotalBytesToDownload());
			BA.Log("Progress = " + progress);
		}
		if (isTerminateState(update.getInstallState())) {
			moduleInstallClient.unregisterListener(this);
		}
	}

	public boolean isTerminateState(@ModuleInstallStatusUpdate.InstallState int state) {
		return state == ModuleInstallStatusUpdate.InstallState.STATE_CANCELED ||
		       state == ModuleInstallStatusUpdate.InstallState.STATE_COMPLETED ||
		       state == ModuleInstallStatusUpdate.InstallState.STATE_FAILED;
	}
}

private void moduleInstall() {
	if (moduleInstallClient == null) {
		// 🔒 Safety guard
		moduleInstallClient = ModuleInstall.getClient(ba.applicationContext);
	}

	InstallStatusListener listener = new ModuleInstallProgressListener();

	OptionalModuleApi optionalModuleApi = GmsBarcodeScanning.getClient(ba.applicationContext);

	ModuleInstallRequest moduleInstallRequest = ModuleInstallRequest.newBuilder()
		.addApi(optionalModuleApi)
		.setListener(listener)
		.build();

	moduleInstallClient.installModules(moduleInstallRequest)
		.addOnSuccessListener(new OnSuccessListener<ModuleInstallResponse>() {
			@Override
			public void onSuccess(@NonNull ModuleInstallResponse response) {
				if (response.areModulesAlreadyInstalled()) {
					if (ba.subExists(eventName + "_module_installed")) {
						ba.raiseEvent2(ba, false, eventName + "_module_installed", true, new Object[]{"Modules are already installed when the request was sent"});
					}
				} else {
					BA.Log("Module install completed.");
				}
			}
		})
		.addOnFailureListener(new OnFailureListener() {
			@Override
			public void onFailure(@NonNull Exception e) {
				BA.Log("Module install ERROR: " + e);
			}
		});
}

#End If
