# [SKRIP 3.3: Batch di latar belakang dengan QgsTask supaya QGIS tidak macet]
# Penulis: Badar Mubarok Yogaswara
import glob
import os
import processing
from qgis.core import QgsApplication, QgsTask, QgsMessageLog, Qgis, QgsRasterLayer, QgsProject

DATA = "D:/Latihan/paket-i4"
HASIL = "D:/Latihan/hasil_i4"
folder_masuk = DATA + "/Ortofoto_Mentah"
folder_keluar = HASIL + "/NDVI_latar"
os.makedirs(folder_keluar, exist_ok=True)


def hitung_ndvi(task, folder_in, folder_out):
    """Berjalan di LATAR BELAKANG. Jangan menyentuh proyek atau antarmuka di sini."""
    daftar = sorted(glob.glob(folder_in + "/*.tif"))
    keluar = []
    for i, jalur in enumerate(daftar):
        if task.isCanceled():                       # pengguna menekan Cancel
            return None
        tujuan = folder_out + "/NDVI_" + os.path.basename(jalur)
        ubin = QgsRasterLayer(jalur, "ubin", "gdal")
        processing.run("native:rastercalc", {
            "EXPRESSION": '("ubin@1" - "ubin@2") / ("ubin@1" + "ubin@2")',
            "LAYERS": [ubin], "OUTPUT": tujuan})
        keluar.append(tujuan)
        task.setProgress(100 * (i + 1) / len(daftar))    # bilah kemajuan di pojok kanan bawah QGIS
    return keluar


def selesai(exception, hasil=None):
    """Berjalan di PROGRAM UTAMA setelah tugas berakhir. Aman untuk menyentuh proyek."""
    if exception is not None:
        QgsMessageLog.logMessage("Tugas gagal: %s" % exception, "Batch NDVI", Qgis.Critical)
    elif hasil is None:
        QgsMessageLog.logMessage("Tugas dibatalkan", "Batch NDVI", Qgis.Warning)
    else:
        for jalur in hasil:
            nama = os.path.basename(jalur)[:-4]
            QgsProject.instance().addMapLayer(QgsRasterLayer(jalur, nama, "gdal"))
        QgsMessageLog.logMessage("Selesai: %d berkas" % len(hasil), "Batch NDVI", Qgis.Success)
        print("Tugas selesai:", len(hasil), "berkas NDVI ditambahkan ke proyek")


tugas = QgsTask.fromFunction("Hitung NDVI semua ubin", hitung_ndvi, on_finished=selesai,
                             folder_in=folder_masuk, folder_out=folder_keluar)
QgsApplication.taskManager().addTask(tugas)
print("Tugas dikirim ke latar belakang. QGIS tetap bisa dipakai.")
